mirror of
https://github.com/diamondburned/arikawa.git
synced 2024-11-01 04:24:19 +00:00
399 lines
14 KiB
Go
399 lines
14 KiB
Go
package discord
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/diamondburned/arikawa/v3/utils/json"
|
|
"github.com/diamondburned/arikawa/v3/utils/json/option"
|
|
)
|
|
|
|
// ChannelFlags are the channel flags combined as a bitfield.
|
|
type ChannelFlags uint64
|
|
|
|
const (
|
|
_ ChannelFlags = 1 << iota
|
|
// PinnedThread means this thread is pinned to the top of its parent
|
|
// GuildForum channel.
|
|
PinnedThread
|
|
_
|
|
_
|
|
// ThreadRequireTag is whether a tag is required to be specified when
|
|
// creating a thread in a GuildForum channel. Tags are specified in the
|
|
// AppliedTags field.
|
|
ThreadRequireTag
|
|
)
|
|
|
|
// Channel represents a guild or DM channel within Discord.
|
|
//
|
|
// https://discord.com/developers/docs/resources/channel#channel-object
|
|
type Channel struct {
|
|
// ID is the id of this channel.
|
|
ID ChannelID `json:"id"`
|
|
// GuildID is the id of the guild.
|
|
//
|
|
// This field may be missing for some channel objects received over gateway
|
|
// guild dispatches.
|
|
GuildID GuildID `json:"guild_id,omitempty"`
|
|
|
|
// Type is the type of channel.
|
|
Type ChannelType `json:"type,omitempty"`
|
|
// NSFW specifies whether the channel is nsfw.
|
|
NSFW bool `json:"nsfw,omitempty"`
|
|
|
|
// Position is the sorting position of the channel.
|
|
Position int `json:"position,omitempty"`
|
|
// Overwrites are the explicit permission overrides for members
|
|
// and roles.
|
|
Overwrites []Overwrite `json:"permission_overwrites,omitempty"`
|
|
|
|
// Name is the name of the channel (2-100 characters).
|
|
Name string `json:"name,omitempty"`
|
|
// Topic is the channel topic (0-1024 characters).
|
|
Topic string `json:"topic,omitempty"`
|
|
|
|
// LastMessageID is the id of the last message sent in this channel (may
|
|
// not point to an existing or valid message).
|
|
LastMessageID MessageID `json:"last_message_id,omitempty"`
|
|
|
|
// VoiceBitrate is the bitrate (in bits) of the voice channel.
|
|
VoiceBitrate uint `json:"bitrate,omitempty"`
|
|
// VoiceUserLimit is the user limit of the voice channel.
|
|
VoiceUserLimit uint `json:"user_limit,omitempty"`
|
|
|
|
// Flags is a bitmask that contains if a thread is pinned, for example.
|
|
Flags ChannelFlags `json:"flags,omitempty"`
|
|
|
|
// UserRateLimit is the amount of seconds a user has to wait before sending
|
|
// another message (0-21600). Bots, as well as users with the permission
|
|
// manage_messages or manage_channel, are unaffected.
|
|
UserRateLimit Seconds `json:"rate_limit_per_user,omitempty"`
|
|
|
|
// DMRecipients are the recipients of the DM.
|
|
DMRecipients []User `json:"recipients,omitempty"`
|
|
// Icon is the icon hash.
|
|
Icon Hash `json:"icon,omitempty"`
|
|
|
|
// OwnerID is the id of the DM or thread creator.
|
|
OwnerID UserID `json:"owner_id,omitempty"`
|
|
// AppID is the application id of the group DM creator if it is
|
|
// bot-created.
|
|
AppID AppID `json:"application_id,omitempty"`
|
|
// ParentID for guild channels: id of the parent category for a channel
|
|
// (each parent category can contain up to 50 channels), for threads: the
|
|
// id of the text channel this thread was created.
|
|
ParentID ChannelID `json:"parent_id,omitempty"`
|
|
|
|
// LastPinTime is when the last pinned message was pinned.
|
|
LastPinTime Timestamp `json:"last_pin_timestamp,omitempty"`
|
|
|
|
// RTCRegionID is the voice region id for the voice channel.
|
|
RTCRegionID string `json:"rtc_region,omitempty"`
|
|
// VideoQualityMode is the camera video quality mode of the voice channel.
|
|
VideoQualityMode VideoQualityMode `json:"video_quality_mode,omitempty"`
|
|
|
|
// MessageCount is an approximate count of messages in a thread. However,
|
|
// counting stops at 50.
|
|
MessageCount int `json:"message_count,omitempty"`
|
|
// MemberCount is an approximate count of users in a thread. However,
|
|
// counting stops at 50.
|
|
MemberCount int `json:"member_count,omitempty"`
|
|
|
|
// ThreadMetadata contains thread-specific fields not needed by other
|
|
// channels.
|
|
ThreadMetadata *ThreadMetadata `json:"thread_metadata,omitempty"`
|
|
// ThreadMember is the thread member object for the current user, if they
|
|
// have joined the thread, only included on certain API endpoints.
|
|
ThreadMember *ThreadMember `json:"thread_member,omitempty"`
|
|
// DefaultAutoArchiveDuration is the default duration for newly created
|
|
// threads, in minutes, to automatically archive the thread after recent
|
|
// activity.
|
|
DefaultAutoArchiveDuration ArchiveDuration `json:"default_auto_archive_duration,omitempty"`
|
|
|
|
// SelfPermissions are the computed permissions for the invoking user in
|
|
// the channel, including overwrites, only included when part of the
|
|
// resolved data received on a slash command interaction.
|
|
SelfPermissions Permissions `json:"permissions,omitempty,string"`
|
|
|
|
// AvailableTags is the set of tags that can be used in a GuildForum
|
|
// channel.
|
|
AvailableTags []Tag `json:"available_tags,omitempty"`
|
|
// AppliedTags are the IDs of the set of tags that have been applied to a
|
|
// thread in a GuildForum channel.
|
|
AppliedTags []TagID `json:"applied_tags,omitempty"`
|
|
// DefaultReactionEmoji is the emoji to show in the add reaction button on a
|
|
// thread in a GuildForum channel
|
|
DefaultReactionEmoji *ForumReaction `json:"default_reaction_emoji,omitempty"`
|
|
// DefaultThreadRateLimitPerUser is the initial rate_limit_per_user to set on newly created threads in a channel. this field is copied to the thread at creation time and does not live update.
|
|
DefaultThreadRateLimitPerUser int `json:"default_thread_rate_limit_per_user,omitempty"`
|
|
// DefaultSoftOrder is the default sort order type used to order posts in GUILD_FORUM channels. Defaults to null, which indicates a preferred sort order hasn't been set by a channel admin.
|
|
DefaultSoftOrder *SortOrderType `json:"default_sort_order,omitempty"`
|
|
// DefaultForumLayout is the default forum layout view used to display posts in GUILD_FORUM channels. Defaults to 0, which indicates a layout view has not been set by a channel admin.
|
|
DefaultForumLayout ForumLayoutType `json:"default_forum_layout,omitempty"`
|
|
}
|
|
|
|
func (ch *Channel) UnmarshalJSON(data []byte) error {
|
|
type RawChannel Channel
|
|
if err := json.Unmarshal(data, (*RawChannel)(ch)); err != nil {
|
|
return err
|
|
}
|
|
|
|
// In the docs, Discord states that if VideoQualityMode is omitted, it is
|
|
// actually 1 aka. AutoVideoQuality, and they just didn't bother to send
|
|
// it.
|
|
// Refer to:
|
|
// https://discord.com/developers/docs/resources/channel#channel-object-channel-structure
|
|
if ch.VideoQualityMode == 0 {
|
|
ch.VideoQualityMode = 1
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CreatedAt returns a time object representing when the channel was created.
|
|
func (ch Channel) CreatedAt() time.Time {
|
|
return ch.ID.Time()
|
|
}
|
|
|
|
// Mention returns a mention of the channel.
|
|
func (ch Channel) Mention() string {
|
|
return ch.ID.Mention()
|
|
}
|
|
|
|
// URL generates a Discord client URL to the channel. If the channel doesn't
|
|
// have a GuildID, it will generate a URL with the guild "@me".
|
|
func (c Channel) URL() string {
|
|
var guildID = "@me"
|
|
if c.GuildID.IsValid() {
|
|
guildID = c.GuildID.String()
|
|
}
|
|
|
|
return fmt.Sprintf(
|
|
"https://discord.com/channels/%s/%s",
|
|
guildID, c.ID.String(),
|
|
)
|
|
}
|
|
|
|
// IconURL returns the URL to the channel icon in the PNG format.
|
|
// An empty string is returned if there's no icon.
|
|
func (ch Channel) IconURL() string {
|
|
return ch.IconURLWithType(PNGImage)
|
|
}
|
|
|
|
// IconURLWithType returns the URL to the channel icon using the passed
|
|
// ImageType. An empty string is returned if there's no icon.
|
|
//
|
|
// Supported ImageTypes: PNG, JPEG, WebP
|
|
func (ch Channel) IconURLWithType(t ImageType) string {
|
|
if ch.Icon == "" {
|
|
return ""
|
|
}
|
|
|
|
return "https://cdn.discordapp.com/channel-icons/" +
|
|
ch.ID.String() + "/" + t.format(ch.Icon)
|
|
}
|
|
|
|
// ChannelType describes the type of the channel.
|
|
//
|
|
// https://discord.com/developers/docs/resources/channel#channel-object-channel-types
|
|
type ChannelType uint16
|
|
|
|
const (
|
|
// GuildText is a text channel within a server.
|
|
GuildText ChannelType = iota
|
|
// DirectMessage is a direct message between users.
|
|
DirectMessage
|
|
// GuildVoice is a voice channel within a server.
|
|
GuildVoice
|
|
// GroupDM is a direct message between multiple users.
|
|
GroupDM
|
|
// GuildCategory is an organizational category that contains up to 50
|
|
// channels.
|
|
GuildCategory
|
|
// GuildAnnouncement is a channel that users can follow and crosspost into
|
|
// their own server.
|
|
GuildAnnouncement
|
|
// GuildStore is a channel in which game developers can sell their game on
|
|
// Discord.
|
|
GuildStore
|
|
_
|
|
_
|
|
_
|
|
// GuildAnnouncementThread is a temporary sub-channel within a GUILD_NEWS channel
|
|
GuildAnnouncementThread
|
|
// GuildPublicThread is a temporary sub-channel within a GUILD_TEXT
|
|
// channel.
|
|
GuildPublicThread
|
|
// GuildPrivateThread isa temporary sub-channel within a GUILD_TEXT channel
|
|
// that is only viewable by those invited and those with the MANAGE_THREADS
|
|
// permission.
|
|
GuildPrivateThread
|
|
// GuildStageVoice is a voice channel for hosting events with an audience.
|
|
GuildStageVoice
|
|
// GuildDirectory is the channel in a hub containing the listed servers.
|
|
GuildDirectory
|
|
// GuildForum is a channel that can only contain threads.
|
|
GuildForum
|
|
)
|
|
|
|
// GuildNews aliases to GuildAnnouncement.
|
|
//
|
|
// Deprecated: use GuildAnnouncement instead.
|
|
const GuildNews = GuildAnnouncement
|
|
|
|
// GuildNewsThread aliases to GuildAnnouncementThread.
|
|
//
|
|
// Deprecated: use GuildAnnouncementThread instead.
|
|
const GuildNewsThread = GuildAnnouncementThread
|
|
|
|
// https://discord.com/developers/docs/resources/channel#overwrite-object
|
|
type Overwrite struct {
|
|
// ID is the role or user id.
|
|
ID Snowflake `json:"id"`
|
|
// Type indicates the entity overwritten: role or member.
|
|
Type OverwriteType `json:"type"`
|
|
// Allow is a permission bit set for granted permissions.
|
|
Allow Permissions `json:"allow,string"`
|
|
// Deny is a permission bit set for denied permissions.
|
|
Deny Permissions `json:"deny,string"`
|
|
}
|
|
|
|
// OverwriteType is an enumerated type to indicate the entity being overwritten:
|
|
// role or member
|
|
type OverwriteType uint8
|
|
|
|
const (
|
|
// OverwriteRole is an overwrite for a role.
|
|
OverwriteRole OverwriteType = iota
|
|
// OverwriteMember is an overwrite for a member.
|
|
OverwriteMember
|
|
)
|
|
|
|
// UnmarshalJSON unmarshalls both a string-quoted number and a regular number
|
|
// into OverwriteType. We need to do this because Discord is so bad that they
|
|
// can't even handle 1s and 0s properly.
|
|
func (otype *OverwriteType) UnmarshalJSON(b []byte) error {
|
|
s := strings.Trim(string(b), `"`)
|
|
|
|
// It has been observed that discord still uses the "legacy" string
|
|
// overwrite types in at least the guild create event.
|
|
// Therefore this string check.
|
|
switch s {
|
|
case "role":
|
|
*otype = OverwriteRole
|
|
return nil
|
|
case "member":
|
|
*otype = OverwriteMember
|
|
return nil
|
|
}
|
|
|
|
u, err := strconv.ParseUint(s, 10, 8)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
*otype = OverwriteType(u)
|
|
return nil
|
|
}
|
|
|
|
type VideoQualityMode uint8
|
|
|
|
// https://discord.com/developers/docs/resources/channel#channel-object-video-quality-modes
|
|
const (
|
|
AutoVideoQuality VideoQualityMode = iota + 1
|
|
FullVideoQuality
|
|
)
|
|
|
|
// ThreadMetadata contains a number of thread-specific channel fields that are
|
|
// not needed by other channel types.
|
|
//
|
|
// https://discord.com/developers/docs/resources/channel#thread-metadata-object
|
|
type ThreadMetadata struct {
|
|
// Archived specifies whether the thread is archived.
|
|
Archived bool `json:"archived"`
|
|
// AutoArchiveDuration is the duration in minutes to automatically archive
|
|
// the thread after recent activity.
|
|
AutoArchiveDuration ArchiveDuration `json:"auto_archive_duration"`
|
|
// ArchiveTimestamp timestamp when the thread's archive status was last
|
|
// changed, used for calculating recent activity.
|
|
ArchiveTimestamp Timestamp `json:"archive_timestamp"`
|
|
// Locked specifies whether the thread is locked; when a thread is locked,
|
|
// only users with MANAGE_THREADS can unarchive it.
|
|
Locked bool `json:"locked"`
|
|
// Invitable specifies whether non-moderators can add other
|
|
// non-moderators to a thread; only available on private threads.
|
|
Invitable bool `json:"invitable,omitempty"`
|
|
// CreateTimestamp is the timestamp when the thread was created; only
|
|
// populated for threads created after 2022-01-09.
|
|
CreateTimestamp *Timestamp `json:"thread_metadata,omitempty"`
|
|
}
|
|
|
|
type ThreadMember struct {
|
|
// ID is the id of the thread.
|
|
//
|
|
// This field will be omitted on the member sent within each thread in the
|
|
// guild create event.
|
|
ID ChannelID `json:"id,omitempty"`
|
|
// UserID is the id of the user.
|
|
//
|
|
// This field will be omitted on the member sent within each thread in the
|
|
// guild create event.
|
|
UserID UserID `json:"user_id,omitempty"`
|
|
// Member is the member, only included in Thread Members Update Events.
|
|
Member *Member `json:"member,omitempty"`
|
|
// Presence is the presence, only included in Thread Members Update Events.
|
|
Presence *Presence `json:"presence,omitempty"`
|
|
// JoinTimestamp is the time the current user last joined the thread.
|
|
JoinTimestamp Timestamp `json:"join_timestamp"`
|
|
// Flags are any user-thread settings.
|
|
Flags ThreadMemberFlags `json:"flags"`
|
|
}
|
|
|
|
// ThreadMemberFlags are the flags of a ThreadMember.
|
|
// Currently, none are documented.
|
|
type ThreadMemberFlags uint64
|
|
|
|
// Tag represents a tag that is able to be applied to a thread in a GuildForum
|
|
// channel.
|
|
type Tag struct {
|
|
ID TagID `json:"id,omitempty"`
|
|
Name string `json:"name"`
|
|
Moderated bool `json:"moderated"`
|
|
ForumReaction
|
|
}
|
|
|
|
// ForumReaction is used in several forum-related structures. It is officially
|
|
// named the "Default Reaction" object.
|
|
type ForumReaction struct {
|
|
// EmojiID is set when there is a custom emoji used.
|
|
// Only one of EmojiID and EmojiName can be set
|
|
EmojiID EmojiID `json:"emoji_id"`
|
|
// EmojiName is set when the emoji is a normal unicode emoji.
|
|
// Only one of EmojiID and EmojiName can be set
|
|
EmojiName option.String `json:"emoji_name"`
|
|
}
|
|
|
|
// https://discord.com/developers/docs/resources/channel#channel-object-sort-order-types
|
|
type SortOrderType uint8
|
|
|
|
const (
|
|
// Sort forum posts by activity.
|
|
SortOrderTypeLatestActivity SortOrderType = iota
|
|
// Sort forum posts by creation time (from most recent to oldest)
|
|
SoftOrderTypeCreationDate
|
|
)
|
|
|
|
// https://discord.com/developers/docs/resources/channel#channel-object-forum-layout-types
|
|
type ForumLayoutType uint8
|
|
|
|
const (
|
|
// No default has been set for forum channel.
|
|
ForumLayoutTypeNotSet ForumLayoutType = iota
|
|
// Display posts as a list.
|
|
ForumLayoutTypeListView
|
|
// Display posts as a collection of tiles.
|
|
ForumLayoutTypeGalleryView
|
|
)
|