diff --git a/disagreement/__init__.py b/disagreement/__init__.py index facba5b..db4015b 100644 --- a/disagreement/__init__.py +++ b/disagreement/__init__.py @@ -15,7 +15,30 @@ __copyright__ = "Copyright 2025 Slipstream" __version__ = "0.4.2" from .client import Client, AutoShardedClient -from .models import Message, User, Reaction, AuditLogEntry +from .models import ( + Message, + User, + Reaction, + AuditLogEntry, + Member, + Role, + Attachment, + Channel, + ActionRow, + Button, + SelectOption, + SelectMenu, + Embed, + PartialEmoji, + Section, + TextDisplay, + Thumbnail, + UnfurledMediaItem, + MediaGallery, + MediaGalleryItem, + Container, + Guild, +) from .voice_client import VoiceClient from .audio import AudioSource, FFmpegAudioSource from .typing import Typing @@ -29,11 +52,22 @@ from .errors import ( ) from .color import Color from .utils import utcnow, message_pager -from .enums import GatewayIntent, GatewayOpcode +from .enums import ( + GatewayIntent, + GatewayOpcode, + ButtonStyle, + ChannelType, + MessageFlags, + InteractionType, + InteractionCallbackType, + ComponentType, +) from .error_handler import setup_global_error_handler from .hybrid_context import HybridContext -from .ext import tasks +from .interactions import Interaction from .logging_config import setup_logging +from . import ui, ext + import logging @@ -45,6 +79,23 @@ __all__ = [ "User", "Reaction", "AuditLogEntry", + "Member", + "Role", + "Attachment", + "Channel", + "ActionRow", + "Button", + "SelectOption", + "SelectMenu", + "Embed", + "PartialEmoji", + "Section", + "TextDisplay", + "Thumbnail", + "UnfurledMediaItem", + "MediaGallery", + "MediaGalleryItem", + "Container", "VoiceClient", "AudioSource", "FFmpegAudioSource", @@ -60,10 +111,18 @@ __all__ = [ "message_pager", "GatewayIntent", "GatewayOpcode", + "ButtonStyle", + "ChannelType", + "MessageFlags", + "InteractionType", + "InteractionCallbackType", + "ComponentType", "setup_global_error_handler", "HybridContext", - "tasks", + "Interaction", "setup_logging", + "ui", + "ext", ] diff --git a/disagreement/ext/__init__.py b/disagreement/ext/__init__.py index 8b13789..f6603f4 100644 --- a/disagreement/ext/__init__.py +++ b/disagreement/ext/__init__.py @@ -1 +1,3 @@ +from . import app_commands, commands, tasks +__all__ = ["app_commands", "commands", "tasks"] diff --git a/examples/basic_bot.py b/examples/basic_bot.py index 5ad01d4..53fead3 100644 --- a/examples/basic_bot.py +++ b/examples/basic_bot.py @@ -27,9 +27,16 @@ if os.path.join(os.getcwd(), "examples") == os.path.dirname(os.path.abspath(__fi sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) try: - import disagreement - from disagreement.models import Guild - from disagreement.ext import commands # Import the new commands extension + from disagreement import ( + Client, + GatewayIntent, + Message, + Guild, + ext, + AuthenticationError, + DisagreementException, + ) + from disagreement.ext import commands except ImportError: print( "Failed to import disagreement. Make sure it's installed or PYTHONPATH is set correctly." @@ -59,15 +66,15 @@ BOT_TOKEN = os.environ.get("DISCORD_BOT_TOKEN") # --- Intents Configuration --- # Define the intents your bot needs. For basic message reading and responding: intents = ( - disagreement.GatewayIntent.GUILDS - | disagreement.GatewayIntent.GUILD_MESSAGES - | disagreement.GatewayIntent.MESSAGE_CONTENT + GatewayIntent.GUILDS + | GatewayIntent.GUILD_MESSAGES + | GatewayIntent.MESSAGE_CONTENT ) # MESSAGE_CONTENT is privileged! # If you don't need message content and only react to commands/mentions, # you might not need MESSAGE_CONTENT intent. -# intents = disagreement.GatewayIntent.default() # A good starting point without privileged intents -# intents |= disagreement.GatewayIntent.MESSAGE_CONTENT # Add if needed +# intents = GatewayIntent.default() # A good starting point without privileged intents +# intents |= GatewayIntent.MESSAGE_CONTENT # Add if needed # --- Initialize the Client --- if not BOT_TOKEN: @@ -76,7 +83,7 @@ if not BOT_TOKEN: sys.exit(1) # Initialize Client with a command prefix -client = disagreement.Client(token=BOT_TOKEN, intents=intents, command_prefix="!") +client = Client(token=BOT_TOKEN, intents=intents, command_prefix="!") # --- Define a Cog for example commands --- @@ -177,7 +184,7 @@ async def on_ready(): @client.event -async def on_message(message: disagreement.Message): +async def on_message(message: Message): """Called when a message is created and received.""" # Command processing is now handled by the CommandHandler via client._process_message_for_commands # This on_message can be used for other message-related logic if needed, @@ -210,11 +217,11 @@ async def main(): # client.add_cog is synchronous, but it schedules cog.cog_load() if it's async. await client.run() - except disagreement.AuthenticationError: + except AuthenticationError: print( "Authentication failed. Please check your bot token and ensure it's correct." ) - except disagreement.DisagreementException as e: + except DisagreementException as e: print(f"A Disagreement library error occurred: {e}") except KeyboardInterrupt: print("Bot shutting down due to KeyboardInterrupt...") diff --git a/examples/component_bot.py b/examples/component_bot.py index d2f9753..b2994e3 100644 --- a/examples/component_bot.py +++ b/examples/component_bot.py @@ -1,8 +1,11 @@ import os import asyncio -from typing import Union, Optional -from disagreement import Client, ui, HybridContext -from disagreement.models import ( +from typing import Union +from disagreement import ( + Client, + ui, + ext, + HybridContext, Message, SelectOption, User, @@ -19,24 +22,14 @@ from disagreement.models import ( MediaGallery, MediaGalleryItem, Container, -) -from disagreement.enums import ( ButtonStyle, GatewayIntent, ChannelType, MessageFlags, - InteractionCallbackType, - MessageFlags, -) -from disagreement.ext.commands.cog import Cog -from disagreement.ext.commands.core import CommandContext -from disagreement.ext.app_commands.decorators import hybrid_command, slash_command -from disagreement.ext.app_commands.context import AppCommandContext -from disagreement.interactions import ( Interaction, - InteractionResponsePayload, - InteractionCallbackData, ) +from disagreement.ext.commands import Cog, CommandContext +from disagreement.ext.app_commands import AppCommandContext, hybrid_command try: from dotenv import load_dotenv diff --git a/examples/context_menus.py b/examples/context_menus.py index 9ba3656..1fe5aad 100644 --- a/examples/context_menus.py +++ b/examples/context_menus.py @@ -7,13 +7,12 @@ import sys 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__), ".."))) -from disagreement.client import Client +from disagreement import Client, User, Message from disagreement.ext.app_commands import ( user_command, message_command, AppCommandContext, ) -from disagreement.models import User, Message try: from dotenv import load_dotenv diff --git a/examples/example_from_readme.py b/examples/example_from_readme.py index acdb411..3d7d4a5 100644 --- a/examples/example_from_readme.py +++ b/examples/example_from_readme.py @@ -4,7 +4,7 @@ import asyncio import os -import disagreement +from disagreement import Client, GatewayIntent from disagreement.ext import commands from dotenv import load_dotenv @@ -12,7 +12,7 @@ load_dotenv() class Basics(commands.Cog): - def __init__(self, client: disagreement.Client) -> None: + def __init__(self, client: Client) -> None: super().__init__(client) @commands.command() @@ -24,12 +24,8 @@ token = os.getenv("DISCORD_BOT_TOKEN") if not token: raise RuntimeError("DISCORD_BOT_TOKEN environment variable not set") -intents = ( - disagreement.GatewayIntent.default() | disagreement.GatewayIntent.MESSAGE_CONTENT -) -client = disagreement.Client( - token=token, command_prefix="!", intents=intents, mention_replies=True -) +intents = GatewayIntent.default() | GatewayIntent.MESSAGE_CONTENT +client = Client(token=token, command_prefix="!", intents=intents, mention_replies=True) async def main() -> None: diff --git a/examples/hybrid_bot.py b/examples/hybrid_bot.py index d4aeae3..077a6fe 100644 --- a/examples/hybrid_bot.py +++ b/examples/hybrid_bot.py @@ -3,32 +3,27 @@ import os import logging from typing import Any, Optional, Literal, Union -from disagreement import HybridContext - -from disagreement.client import Client -from disagreement.ext.commands.cog import Cog -from disagreement.ext.commands.core import CommandContext -from disagreement.ext.app_commands.decorators import ( - slash_command, - user_command, - message_command, - hybrid_command, -) -from disagreement.ext.app_commands.commands import ( - AppCommandGroup, -) # For defining groups -from disagreement.ext.app_commands.context import AppCommandContext # Added -from disagreement.models import ( +from disagreement import ( + HybridContext, + Client, User, Member, Role, Attachment, Message, Channel, -) # For type hints -from disagreement.enums import ( ChannelType, -) # For channel option type hints, assuming it exists +) +from disagreement.ext import commands +from disagreement.ext.commands import Cog, CommandContext +from disagreement.ext.app_commands import ( + AppCommandContext, + AppCommandGroup, + slash_command, + user_command, + message_command, + hybrid_command, +) # from disagreement.interactions import Interaction # Replaced by AppCommandContext diff --git a/examples/message_history.py b/examples/message_history.py index d5c6ffc..b050d35 100644 --- a/examples/message_history.py +++ b/examples/message_history.py @@ -8,7 +8,7 @@ import sys 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__), ".."))) -from disagreement.client import Client +from disagreement import Client, Channel from disagreement.models import TextChannel try: diff --git a/examples/modal_command.py b/examples/modal_command.py index 17e5da8..71b14d0 100644 --- a/examples/modal_command.py +++ b/examples/modal_command.py @@ -9,10 +9,9 @@ except ImportError: # pragma: no cover - example helper load_dotenv = None print("python-dotenv is not installed. Environment variables will not be loaded") -from disagreement import Client, ui -from disagreement.enums import GatewayIntent, TextInputStyle -from disagreement.ext.app_commands.decorators import slash_command -from disagreement.ext.app_commands.context import AppCommandContext +from disagreement import Client, ui, GatewayIntent +from disagreement.enums import TextInputStyle +from disagreement.ext.app_commands import slash_command, AppCommandContext if load_dotenv: load_dotenv() diff --git a/examples/modal_send.py b/examples/modal_send.py index 8e91dba..5b87fd6 100644 --- a/examples/modal_send.py +++ b/examples/modal_send.py @@ -11,9 +11,8 @@ except ImportError: # pragma: no cover - example helper sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) -from disagreement import Client, GatewayIntent, ui # type: ignore -from disagreement.ext.app_commands.decorators import slash_command -from disagreement.ext.app_commands.context import AppCommandContext +from disagreement import Client, GatewayIntent, ui +from disagreement.ext.app_commands import slash_command, AppCommandContext if load_dotenv: load_dotenv() diff --git a/examples/moderation_bot.py b/examples/moderation_bot.py index f5adc2d..8143985 100644 --- a/examples/moderation_bot.py +++ b/examples/moderation_bot.py @@ -9,9 +9,8 @@ from typing import Set 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__), ".."))) -import disagreement +from disagreement import Client, GatewayIntent, Member, Message from disagreement.ext import commands -from disagreement.models import Member, Message try: from dotenv import load_dotenv @@ -28,18 +27,18 @@ if not BOT_TOKEN: sys.exit(1) intents = ( - disagreement.GatewayIntent.GUILDS - | disagreement.GatewayIntent.GUILD_MESSAGES - | disagreement.GatewayIntent.MESSAGE_CONTENT + GatewayIntent.GUILDS + | GatewayIntent.GUILD_MESSAGES + | GatewayIntent.MESSAGE_CONTENT ) -client = disagreement.Client(token=BOT_TOKEN, command_prefix="!", intents=intents) +client = Client(token=BOT_TOKEN, command_prefix="!", intents=intents) # Simple list of banned words BANNED_WORDS: Set[str] = {"badword1", "badword2"} class ModerationCog(commands.Cog): - def __init__(self, bot: disagreement.Client) -> None: + def __init__(self, bot: Client) -> None: super().__init__(bot) @commands.command() diff --git a/examples/reactions.py b/examples/reactions.py index 41b535d..6912721 100644 --- a/examples/reactions.py +++ b/examples/reactions.py @@ -25,9 +25,16 @@ if os.path.join(os.getcwd(), "examples") == os.path.dirname(os.path.abspath(__fi sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) try: - import disagreement + from disagreement import ( + Client, + GatewayIntent, + Reaction, + User, + Member, + HTTPException, + AuthenticationError, + ) from disagreement.ext import commands - from disagreement.models import Reaction, User, Member except ImportError: print( "Failed to import disagreement. Make sure it's installed or PYTHONPATH is set correctly." @@ -50,10 +57,10 @@ BOT_TOKEN = os.environ.get("DISCORD_BOT_TOKEN") # We need GUILDS for server context, GUILD_MESSAGES to receive messages, # and GUILD_MESSAGE_REACTIONS to listen for reaction events. intents = ( - disagreement.GatewayIntent.GUILDS - | disagreement.GatewayIntent.GUILD_MESSAGES - | disagreement.GatewayIntent.GUILD_MESSAGE_REACTIONS - | disagreement.GatewayIntent.MESSAGE_CONTENT # For commands + GatewayIntent.GUILDS + | GatewayIntent.GUILD_MESSAGES + | GatewayIntent.GUILD_MESSAGE_REACTIONS + | GatewayIntent.MESSAGE_CONTENT # For commands ) # --- Initialize the Client --- @@ -61,7 +68,7 @@ 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="!") +client = Client(token=BOT_TOKEN, intents=intents, command_prefix="!") # --- Define a Cog for reaction-related commands --- @@ -76,7 +83,7 @@ class ReactionCog(commands.Cog): # The emoji can be a standard Unicode emoji or a custom one in the format '<:name:id>' await ctx.message.add_reaction("👍") print(f"Reacted to command from {ctx.author.username}") - except disagreement.HTTPException as e: + except HTTPException as e: print(f"Failed to add reaction: {e}") await ctx.reply( "I couldn't add the reaction. I might be missing permissions." @@ -133,7 +140,7 @@ async def main(): try: client.add_cog(ReactionCog(client)) await client.run() - except disagreement.AuthenticationError: + except AuthenticationError: print("Authentication failed. Check your bot token.") except Exception as e: print(f"An unexpected error occurred: {e}") diff --git a/examples/sharded_bot.py b/examples/sharded_bot.py index 0d5e756..6893671 100644 --- a/examples/sharded_bot.py +++ b/examples/sharded_bot.py @@ -8,7 +8,7 @@ import sys 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__), ".."))) -import disagreement +from disagreement import Client try: from dotenv import load_dotenv @@ -23,7 +23,7 @@ TOKEN = os.environ.get("DISCORD_BOT_TOKEN") if not TOKEN: raise RuntimeError("DISCORD_BOT_TOKEN environment variable not set") -client = disagreement.Client(token=TOKEN, shard_count=2) +client = Client(token=TOKEN, shard_count=2) @client.event diff --git a/examples/typing_indicator.py b/examples/typing_indicator.py index dc3b7c4..8442285 100644 --- a/examples/typing_indicator.py +++ b/examples/typing_indicator.py @@ -24,7 +24,7 @@ if os.path.join(os.getcwd(), "examples") == os.path.dirname(os.path.abspath(__fi sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) try: - import disagreement + from disagreement import Client, GatewayIntent, HTTPException, AuthenticationError from disagreement.ext import commands except ImportError: print( @@ -46,9 +46,9 @@ BOT_TOKEN = os.environ.get("DISCORD_BOT_TOKEN") # --- Intents Configuration --- intents = ( - disagreement.GatewayIntent.GUILDS - | disagreement.GatewayIntent.GUILD_MESSAGES - | disagreement.GatewayIntent.MESSAGE_CONTENT + GatewayIntent.GUILDS + | GatewayIntent.GUILD_MESSAGES + | GatewayIntent.MESSAGE_CONTENT ) # --- Initialize the Client --- @@ -56,7 +56,7 @@ 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="!") +client = Client(token=BOT_TOKEN, intents=intents, command_prefix="!") # --- Define a Cog for the typing indicator command --- @@ -76,7 +76,7 @@ class TypingCog(commands.Cog): await asyncio.sleep(5) print("Typing indicator stopped.") await ctx.send("Done!") - except disagreement.HTTPException as e: + except 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." @@ -104,7 +104,7 @@ async def main(): try: client.add_cog(TypingCog(client)) await client.run() - except disagreement.AuthenticationError: + except AuthenticationError: print("Authentication failed. Check your bot token.") except Exception as e: print(f"An unexpected error occurred: {e}") diff --git a/examples/voice_bot.py b/examples/voice_bot.py index 077fccd..b9ab01e 100644 --- a/examples/voice_bot.py +++ b/examples/voice_bot.py @@ -16,7 +16,7 @@ except ImportError: # pragma: no cover - example helper load_dotenv = None print("python-dotenv is not installed. Environment variables will not be loaded") -import disagreement +from disagreement import Client if load_dotenv: load_dotenv() @@ -39,7 +39,7 @@ CHANNEL_ID = cast(str, _CHANNEL_ID) async def main() -> None: - client = disagreement.Client(TOKEN) + client = Client(TOKEN) await client.connect() voice = await client.join_voice(GUILD_ID, CHANNEL_ID) try: