# `Vibe.Gateway.Message`
[🔗](https://github.com/elixir-vibe/vibe/blob/v0.2.3/lib/vibe/gateway/message.ex#L1)

Normalized inbound message from an external chat gateway.

Platform adapters should download/copy media to local files or session
artifacts before constructing this struct. The rest of Vibe can then process
text, attachments, source identity, and replies without depending on Telegram
or any other platform SDK.

# `media`

```elixir
@type media() :: %{
  path: String.t(),
  mime_type: String.t() | nil,
  filename: String.t() | nil
}
```

# `message_type`

```elixir
@type message_type() ::
  :text
  | :command
  | :photo
  | :video
  | :audio
  | :voice
  | :document
  | :sticker
  | :location
```

# `t`

```elixir
@type t() :: %Vibe.Gateway.Message{
  id: String.t() | nil,
  media: [media()],
  metadata: map(),
  platform_update_id: String.t() | integer() | nil,
  reply_to_message_id: String.t() | nil,
  reply_to_text: String.t() | nil,
  source: Vibe.Gateway.Source.t(),
  text: String.t(),
  timestamp: DateTime.t() | nil,
  type: message_type()
}
```

# `command`

```elixir
@spec command(t()) :: String.t() | nil
```

Extracts a slash command name without the leading slash or bot suffix.

# `command?`

```elixir
@spec command?(t()) :: boolean()
```

Returns true when the message text starts with a slash command.

# `command_args`

```elixir
@spec command_args(t()) :: String.t()
```

Returns the text after a slash command, normalizing common mobile dash substitutions.

# `new`

```elixir
@spec new(
  Vibe.Gateway.Source.t(),
  keyword()
) :: t()
```

Builds a normalized gateway message.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
