hikari

repository·master·Indexed 21 days ago

https://github.com/hikari-py/hikari

An opinionated, statically typed Discord microframework for Python 3 and asyncio. It provides high-performance access to Discord's v10 REST and Gateway APIs through three primary implementations: GatewayBot for real-time event listening, RESTBot for interaction-only bots, and RESTApp for REST-only applications.

Tokens
34.7K
Snippets
126
Records
171
Agent score
75%

What's inside hikari

  1. How GatewayBot works

    master

    A GatewayBot connects to Discord via the Gateway to receive real-time events. It is suitable for bots that need to react to various Discord events like messages, presence updates, or member changes.

    Key Features:

    • Event Listening: Use the @bot.listen() decorator. Events are determined by the type annotation of the parameter or by passing the event type to the decorator.
    • Intents: By default, GatewayBot enables all unprivileged intents. To enable all intents (including privileged ones like presence or message content), pass intents=hikari.Intents.ALL to the constructor.
    • Event Filtering: You can filter events within your listener (e.g., checking event.is_human to ignore bots/webhooks).
    import hikari
    
    bot = hikari.GatewayBot(token="...")
    
    @bot.listen()
    async def ping(event: hikari.GuildMessageCreateEvent) -> None:
        if not event.is_human:
            return
    
        me = bot.get_me()
        if me.id in event.message.user_mentions_ids:
            await event.message.respond("Pong!")
    
    bot.run()
  2. Use RESTBot for interaction-only bots

    master

    A RESTBot handles interactions received via an HTTP endpoint.

    Implementation Details:

    • Listeners: Unlike GatewayBot, listeners are registered using .set_listener(EventType, handler_function).
    • Startup Callbacks: Use .add_startup_callback(callback) to run logic (like registering slash commands) when the bot starts.
    • Setup: Requires token, token_type, and public_key during initialization. You must also set the 'Interactions Endpoint URL' in the Discord Developer Portal.
    import asyncio
    import hikari
    
    async def handle_command(interaction: hikari.CommandInteraction):
        yield interaction.build_deferred_response()
        await asyncio.sleep(5)
        await interaction.edit_initial_response("Edit after 5 seconds!")
    
    async def create_commands(bot: hikari.RESTBot):
        application = await bot.rest.fetch_application()
        await bot.rest.set_application_commands(
            application=application.id,
            commands=[
                bot.rest.slash_command_builder("test", "My first test command!"),
            ],
        )
    
    bot = hikari.RESTBot(
        token="...",
        token_type="...",
        public_key="...",
    )
    
    bot.add_startup_callback(create_commands)
    bot.set_listener(hikari.CommandInteraction, handle_command)
    
    bot.run()
  3. Use uvloop for additional performance on UNIX-like systems

    master

    If you are running on a UNIX-like system, you can replace the default asyncio event loop with uvloop (which uses libuv) for better performance. Install it via pip and set the event loop policy at the start of your application.

    import asyncio
    import os
    
    if os.name != "nt":
        import uvloop
        asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
    
    # Your code goes here
  4. Optimize Python execution with CPython flags

    master

    When running your bot in production, it is recommended to use at least first-level optimization to remove internal safety checks.

    • python bot.py: Default (no optimization).
    • python -O bot.py: First level optimization (disables internal assertions).
    • python -OO bot.py: Second level optimization (removes all docstrings from loaded code at runtime).
  5. Optimize Hikari performance with speedups

    master

    To achieve a substantial performance boost, install Hikari with the [speedups] extra. This installs aiohttp with available speedups, ciso8601, and orjson. This requires a C compiler (such as Microsoft VC++ Redistributable 14.0+ or a modern GCC/G++/Clang).

    pip install -U hikari[speedups]
  6. Import core Hikari modules

    master

    The hikari package exports several submodules that organize the Discord API surface. Common modules include:

    • hikari.api: Low-level API definitions.
    • hikari.applications: Application and OAuth2 related types.
    • hikari.channels: Channel-related types and constants.
    • hikari.commands: Command structures.
    • hikari.events: The hierarchy of event types (e.g., MessageCreateEvent, GuildMemberAddEvent).
    • hikari.interactions: Interaction types (Commands, Components, Modals).
    • hikari.messages: Message-related data structures.
    • hikari.snowflakes: Snowflake ID handling.
    • hikari.users: User-related types.

    Most high-level objects and constants are available directly from the top-level hikari namespace due to star imports in the package initialization.

  7. Understand Application installation types and contexts

    master

    Discord allows applications to be installed in different ways and used in different contexts:

    ApplicationIntegrationType (Where it can be installed):

    • GUILD_INSTALL (0): Installable to all guilds.
    • USER_INSTALL (1): Installable to all users.

    ApplicationContextType (Where commands can be run):

    • GUILD (0): Inside servers.
    • BOT_DM (1): Inside the bot's DM.
    • PRIVATE_CHANNEL (2): Inside any user's DM or Group DM (excluding the bot's DM).
  8. Manipulate permissions with the Permissions class

    master

    The Permissions class is an enum.IntFlag representing Discord permissions. It uses a bitfield, allowing you to combine, compare, and calculate permission sets using standard bitwise operators.

    Combining Permissions

    Use the bitwise OR operator (|) to combine multiple permissions into a single set.

    Checking for Required Permissions

    To check if a user has all permissions from a required set, use the bitwise AND (&) operator and compare the result to the required set using ==.

    Finding Missing Permissions

    To find which permissions from a required set are missing from a user's current permissions, use the bitwise NOT (~) and AND (&) operators: ~my_perms & required_perms.

    Excluding Permissions

    To create a set that includes all permissions except specific ones, use the bitwise NOT (~) operator.

    # Combining permissions
    my_perms = Permissions.MANAGE_CHANNELS | Permissions.MANAGE_GUILD
    
    # Checking if all required permissions are present
    required_perms = Permissions.CREATE_INSTANT_INVITE | Permissions.KICK_MEMBERS
    if (my_perms & required_perms) == required_perms:
        print("I have all of the required permissions!")
    
    # Finding missing permissions
    missing_perms = ~my_perms & required_perms
    if missing_perms:
        print(f"I'm missing these permissions: {missing_perms}")
    
    # All permissions except ADMINISTRATOR
    my_perms = ~Permissions.ADMINISTRATOR
  9. Handle Hikari errors and warnings

    master
    All errors raised by the Hikari library derive from HikariError (a subclass of RuntimeError). Warnings derive from HikariWarning (a subclass of RuntimeWarning). You should catch these base classes if you want to handle all library-specific issues, or catch specific subclasses for granular error handling.
  10. Handle HTTP and REST errors

    master

    Errors occurring during REST requests derive from HTTPError.

    HTTP Response Errors

    HTTPResponseError is the base for erroneous responses and contains the url, status (HTTP status code), headers, raw_body, and message.

    • InternalServerError: Base for 5xx server errors.
    • ClientHTTPResponseError: Base for 4xx client errors.
      • BadRequestError: Raised for invalid requests (400). Includes an errors mapping for field-specific error details.
      • UnauthorizedError: Raised when not authorized (401).
      • ForbiddenError: Raised when lacking permissions (403).
      • NotFoundError: Raised when a resource is not found (404).

    Rate Limiting

    RateLimitTooLongError is raised preemptively if a rate limit wait time exceeds the user-defined max_retry_after limit. It provides details like retry_after, reset_at, and is_global.

  11. Use the UNDEFINED sentinel for optional values

    master

    Hikari uses a singleton sentinel UNDEFINED to distinguish between a value being explicitly set to None (representing an empty or null state) and a value being omitted entirely (representing the default state).

    This is particularly important in REST API calls (like edit_message) where:

    • Passing None might clear a field.
    • Passing UNDEFINED tells the library to leave the field unchanged.

    Think of UNDEFINED as undefined in JavaScript, whereas None is equivalent to null.

    from hikari import UNDEFINED
    
    # Example: Distinguishing between clearing a value and omitting it
    # (Conceptual usage in API calls)
    await client.edit_message(message_id, content=None)      # Clears the content
    await client.edit_message(message_id, content=UNDEFINED)  # Leaves content unchanged