Initial commit.

This commit is contained in:
2026-02-14 15:20:52 -05:00
commit 067b7c5a0a
48 changed files with 12169 additions and 0 deletions
+108
View File
@@ -0,0 +1,108 @@
# Copyright 2026 Logan Fick
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command system types and decorators for Owlbot.
This module provides the module-facing API for commands:
- @on_command decorator for registering command handlers
- CommandEvent dataclass for parsed command data
- CommandInfo dataclass for command metadata
- CommandHandler type alias
"""
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, TypedDict
if TYPE_CHECKING:
from collections.abc import Awaitable, Callable
from .context import CommandContext
from .event_types import ChatEvent
class CommandMark(TypedDict):
"""Type for the command marker attribute set by @on_command."""
name: str
aliases: list[str] | tuple[str, ...] | None
requires_authenticated: bool
requires_moderator: bool
cooldown: int | float
@dataclass
class CommandEvent:
"""Parsed command information from a chat message."""
command: str
args: str
args_list: list[str]
prefix: str
chat_event: ChatEvent
type CommandHandler = "Callable[[CommandContext], Awaitable[None]]"
@dataclass
class CommandInfo:
"""Metadata about a registered command."""
name: str
handler: CommandHandler
module_name: str
aliases: frozenset[str] = field(default_factory=frozenset)
requires_authenticated: bool = False
requires_moderator: bool = False
cooldown: int | float = 0
@property
def all_triggers(self) -> frozenset[str]:
"""All names that trigger this command (name + aliases)."""
return frozenset({self.name}) | self.aliases
def on_command(
name: str,
*,
aliases: list[str] | tuple[str, ...] | None = None,
requires_authenticated: bool = False,
requires_moderator: bool = False,
cooldown: int | float = 0,
) -> Callable[[CommandHandler], CommandHandler]:
"""
Decorator to register a command handler.
:param name: Primary command name (case-insensitive).
:param aliases: Optional list of alternative names.
:param requires_authenticated: If True, user must be logged in.
:param requires_moderator: If True, user must have moderator privileges.
:param cooldown: Minimum seconds between invocations, global across all
users (0 to disable).
:return: Decorator that marks the function for registration.
"""
def decorator(func: CommandHandler) -> CommandHandler:
# Mark the function with command info for deferred registration.
# The module loader will scan for this attribute and register commands.
func._owlbot_command = CommandMark( # type: ignore[attr-defined]
name=name,
aliases=aliases,
requires_authenticated=requires_authenticated,
requires_moderator=requires_moderator,
cooldown=cooldown,
)
return func
return decorator