> ## Documentation Index
> Fetch the complete documentation index at: https://docs.guilt.icu/llms.txt
> Use this file to discover all available pages before exploring further.

# alterself Data Models: User, Guild, Channel, Message

> Reference for all alterself model objects returned by gateway events and HTTP methods, including User, Guild, Channel, Message, Member, and Flake.

alterself represents every Discord resource as a typed model object. These objects behave like Python dataclasses. Each attribute is strongly typed and populated automatically when the gateway dispatches an event or when an HTTP method returns a response. In addition to raw attributes, most models expose computed properties that derive useful values (such as CDN URLs, mentions, and creation timestamps) without requiring extra API calls.

***

## User

The `User` model represents any Discord account: a human user, a bot, or the account your selfbot is logged into. You receive `User` objects from gateway events such as `READY`, `MESSAGE_CREATE`, and relationship events.

### Attributes

| Attribute | Type | Description |
| - | - | - |
| `id` | `Flake` | Discord snowflake that uniquely identifies this user. |
| `username` | `str` | The user's account username. |
| `discriminator` | `str` | Legacy four-digit discriminator (e.g. `"0"` for migrated accounts). |
| `global_name` | `str \| None` | Display name under the new username system; `None` for unmigrated accounts. |
| `avatar` | `str \| None` | Avatar image hash. Pass to `avatar_url` to build a full CDN URL. |
| `bot` | `bool` | `True` if this account is a bot application. |
| `public_flags` | `int` | Bitfield of public badge flags (e.g. Early Supporter, HypeSquad). |
| `premium_type` | `int` | Nitro subscription tier: `0` = None, `1` = Classic, `2` = Nitro, `3` = Basic. |

### Properties

| Property | Type | Description |
| - | - | - |
| `display_name` | `str` | Returns `global_name` if set, otherwise falls back to `username`. |
| `mention` | `str` | A ready-to-send mention string in the format `<@id>`. |
| `avatar_url` | `str \| None` | Full Discord CDN URL for the user's avatar, or `None` if no avatar is set. |
| `created_at` | `datetime` | UTC `datetime` derived from the snowflake, representing when the account was created. |

```python theme={null}
user = bot.user
print(user.display_name)   # global_name or username
print(user.mention)        # <@123456789012345678>
print(user.avatar_url)     # https://cdn.discordapp.com/avatars/...
print(user.created_at)     # 2020-01-01 00:00:00+00:00
```

<Tip>
  Use `display_name` instead of `username` when presenting a user to humans. It always returns the most visible name regardless of whether the account has migrated to the new system.
</Tip>

***

## Guild

The `Guild` model represents a Discord server. alterself populates guild objects from `GUILD_CREATE` events and caches them for the lifetime of the session.

### Attributes

| Attribute | Type | Description |
| - | - | - |
| `id` | `Flake` | Unique guild snowflake ID. |
| `name` | `str` | The guild's display name. |
| `icon` | `str \| None` | Icon image hash, or `None` if no icon is set. |
| `owner_id` | `Flake \| None` | Snowflake of the guild owner's user account. |
| `member_count` | `int` | Approximate number of members at the time of the last `GUILD_CREATE` event. |
| `premium_tier` | `int` | Server boost tier: `0` = none, `1` = Tier 1, `2` = Tier 2, `3` = Tier 3. |
| `description` | `str \| None` | Community description set by guild administrators, or `None`. |

### Properties

| Property | Type | Description |
| - | - | - |
| `channels` | `list[Channel]` | All cached channels that belong to this guild. |
| `members` | `list[Member]` | All cached members in this guild. |
| `icon_url` | `str \| None` | Full Discord CDN URL for the guild's icon, or `None` if no icon is set. |

```python theme={null}
guild = bot.get_guild(guild_id)
print(guild.name)
print(guild.premium_tier)    # 0, 1, 2, or 3
for channel in guild.channels:
    print(channel.name)
```

<Note>
  `member_count` reflects the count at the time the guild payload was received. It is **not** updated incrementally as members join or leave. Use `GUILD_MEMBER_ADD` and `GUILD_MEMBER_REMOVE` events to track live changes.
</Note>

***

## Channel

The `Channel` model represents any Discord channel: text, voice, category, thread, or DM. The `kind` attribute tells you which type you are dealing with.

### Attributes

| Attribute | Type | Description |
| - | - | - |
| `id` | `Flake` | Unique channel snowflake ID. |
| `kind` | `ChannelKind` | Enum value describing the channel type (e.g. `ChannelKind.TEXT`, `ChannelKind.DM`). |
| `name` | `str \| None` | Channel name, or `None` for DM channels. |
| `guild_id` | `Flake \| None` | Snowflake of the guild this channel belongs to, or `None` for DMs. |
| `topic` | `str \| None` | Channel topic text, or `None` if unset. |
| `nsfw` | `bool` | `True` if the channel is marked as age-restricted. |
| `parent_id` | `Flake \| None` | Snowflake of the parent category, or parent channel for threads. |

### Properties

| Property | Type | Description |
| - | - | - |
| `mention` | `str` | A ready-to-send channel mention in the format `<#id>`. |

```python theme={null}
channel = bot.get_channel(channel_id)
print(channel.mention)   # <#123456789012345678>
print(channel.kind)      # ChannelKind.TEXT
```

### Subclasses

#### DMChannel

`DMChannel` extends `Channel` and is returned for private messages between you and another user.

| Attribute | Type | Description |
| - | - | - |
| `recipient` | `User \| None` | The other participant in the DM, or `None` if not cached. |

#### GroupChannel

`GroupChannel` extends `Channel` and represents a group DM.

| Attribute | Type | Description |
| - | - | - |
| `recipients` | `list[User]` | All participants in the group DM. |
| `owner_id` | `Flake \| None` | Snowflake of the user who owns the group DM. |

<Tip>
  Check `channel.guild_id is None` to quickly determine whether a channel is a DM rather than importing `ChannelKind` and comparing against every DM variant.
</Tip>

***

## Message

The `Message` model represents a Discord message. You receive message objects primarily from `MESSAGE_CREATE` and `MESSAGE_UPDATE` gateway events, and from HTTP fetch methods.

### Attributes

| Attribute | Type | Description |
| - | - | - |
| `id` | `Flake` | Unique message snowflake ID. |
| `channel_id` | `Flake` | Snowflake of the channel this message was sent in. |
| `guild_id` | `Flake \| None` | Snowflake of the guild, or `None` for DMs. |
| `author` | `User \| None` | The user who sent the message, or `None` if not available in the payload. |
| `content` | `str` | Plain text content of the message. |
| `timestamp` | `datetime \| None` | UTC timestamp of when the message was sent, or `None` if not present in the payload. |
| `edited_timestamp` | `datetime \| None` | UTC timestamp of the last edit, or `None` if never edited. |
| `attachments` | `list[dict]` | List of attachment objects included with the message. |
| `embeds` | `list[dict]` | List of embed objects included with the message. |
| `reactions` | `list[dict]` | List of reaction objects on the message. |
| `pinned` | `bool` | `True` if the message is pinned in its channel. |
| `kind` | `MessageKind` | Enum value describing the message type (e.g. `MessageKind.DEFAULT`, `MessageKind.REPLY`). |
| `flags` | `int` | Bitfield of message flags. |
| `referenced_message` | `Message \| None` | The message being replied to, or `None` if not a reply or not cached. |

### Properties

| Property | Type | Description |
| - | - | - |
| `channel` | `Channel \| None` | The cached `Channel` object for `channel_id`, or `None` if not in cache. |
| `guild` | `Guild \| None` | The cached `Guild` object for `guild_id`, or `None` if a DM or not in cache. |
| `jump_url` | `str` | A `discord.com/channels/...` deep-link URL that opens this message in the client. |

```python theme={null}
@bot.on("MESSAGE_CREATE")
async def on_message(msg):
    print(msg.author.display_name)
    print(msg.content)
    print(msg.jump_url)
    if msg.referenced_message:
        print("Reply to:", msg.referenced_message.content)
```

<Warning>
  `channel` and `guild` resolve against the in-memory cache. If alterself has not yet received the corresponding `CHANNEL_CREATE` or `GUILD_CREATE` event, for example immediately after connecting, these properties may return `None` even when `channel_id` and `guild_id` are set.
</Warning>

***

## Member

The `Member` model represents a user's membership within a specific guild. It combines guild-specific metadata with a reference back to the underlying `User` object.

### Attributes

| Attribute | Type | Description |
| - | - | - |
| `id` | `Flake` | The user's snowflake ID (same as `user.id`). |
| `guild_id` | `Flake \| None` | Snowflake of the guild this membership belongs to, or `None` if not available. |
| `nick` | `str \| None` | Guild-specific nickname, or `None` if not set. |
| `roles` | `list[Flake]` | Snowflakes of every role assigned to this member. |
| `joined_at` | `str \| None` | ISO 8601 timestamp string of when the member joined the guild, or `None` if not available. |
| `deaf` | `bool` | `True` if the member is server-deafened in voice. |
| `mute` | `bool` | `True` if the member is server-muted in voice. |
| `pending` | `bool` | `True` if the member has not yet passed the membership screening. |

### Properties

| Property | Type | Description |
| - | - | - |
| `user` | `User \| None` | The underlying `User` object, resolved from cache. `None` if not cached. |
| `display_name` | `str` | Returns `nick` if set, then `user.display_name` if the user is cached, otherwise the raw ID as a string. |

```python theme={null}
@bot.on("GUILD_MEMBER_ADD")
async def on_join(member):
    print(f"{member.display_name} joined {member.guild_id}")
    print(f"Roles: {member.roles}")
```

***

## Flake

`Flake` is alterself's wrapper around a Discord snowflake ID. Every model's `id` attribute is a `Flake`, not a plain integer, but `Flake` compares and hashes as an integer, so you can use it wherever an `int` is expected.

The real value of `Flake` is the structured data it exposes directly from the 64-bit snowflake value.

```python theme={null}
msg.id.created_at    # datetime - UTC creation time derived from the snowflake
msg.id.timestamp_ms  # int - Unix timestamp in milliseconds
msg.id.worker_id     # int - Internal Discord worker ID (bits 17–21)
msg.id.process_id    # int - Internal Discord process ID (bits 12–16)
msg.id.increment     # int - Per-process increment counter (bits 0–11)
```

```python theme={null}
flake = msg.id
print(int(flake))           # 123456789012345678
print(flake.created_at)     # 2021-03-24 17:08:21.141000+00:00
print(flake.timestamp_ms)   # 1616605701141
print(flake == 123456789012345678)  # True
```

<Note>
  `Flake` objects are safe to use as dictionary keys and in sets. Two `Flake` objects with the same integer value are considered equal and produce the same hash.
</Note>
