1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2025-12-01 17:00:56 +00:00

Added Permissions and stuff

This commit is contained in:
diamondburned 2020-01-03 20:19:24 -08:00
parent b77d5f20da
commit 6b993f2032
12 changed files with 671 additions and 31 deletions

View file

@ -9,7 +9,7 @@ import (
const EndpointChannels = Endpoint + "channels/"
type ChannelModifier struct {
ChannelID discord.Snowflake `json:"id,omitempty"`
ChannelID discord.Snowflake `json:"id,string,omitempty"`
// All types
Name string `json:"name,omitempty"`
@ -30,10 +30,12 @@ type ChannelModifier struct {
UserLimit json.OptionUint `json:"user_limit,omitempty"`
// Text OR Voice
ParentID discord.Snowflake `json:"parent_id,omitempty"`
ParentID discord.Snowflake `json:"parent_id,string,omitempty"`
}
func (c *Client) Channel(channelID discord.Snowflake) (*discord.Channel, error) {
func (c *Client) Channel(
channelID discord.Snowflake) (*discord.Channel, error) {
var channel *discord.Channel
return channel,

View file

@ -1,7 +1,10 @@
package api
import (
"errors"
"github.com/diamondburned/arikawa/discord"
"github.com/diamondburned/arikawa/httputil"
)
// EmojiAPI is a special format that the API wants.
@ -31,4 +34,61 @@ func (c *Client) Emoji(
EndpointGuilds+guildID.String()+"/emojis/"+emojiID.String())
}
// func (c *Client) CreateEmoji()
var (
ErrEmojiTooLarge = errors.New("Emoji is larger than 256k")
)
// CreateEmoji creates a new emoji in the guild. This endpoint requires
// MANAGE_EMOJIS. ContentType must be "image/jpeg", "image/png", or
// "image/gif". However, ContentType can also be automatically detected
// (though shouldn't be relied on). Roles slice is optional.
func (c *Client) CreateEmoji(
guildID discord.Snowflake, name string, image Image,
roles []discord.Snowflake) (*discord.Emoji, error) {
image.MaxSize = 256 * 1000
if err := image.Validate(); err != nil {
return nil, err
}
var param struct {
Name string `json:"name"`
Image Image `json:"image"`
Roles []discord.Snowflake `json:"roles"`
}
param.Name = name
param.Roles = roles
param.Image = image
var emj *discord.Emoji
return emj, c.RequestJSON(
&emj, "POST",
EndpointGuilds+guildID.String()+"/emojis",
httputil.WithJSONBody(c, param),
)
}
// ModifyEmoji changes an existing emoji. This requires MANAGE_EMOJIS. Name and
// roles are optional fields (though you'd want to change either though).
func (c *Client) ModifyEmoji(
guildID, emojiID discord.Snowflake, name string,
roles []discord.Snowflake) error {
var param struct {
Name string `json:"name,omitempty"`
Roles []discord.Snowflake `json:"roles,omitempty"`
}
return c.FastRequest(
"PATCH",
EndpointGuilds+guildID.String()+"/emojis/"+emojiID.String(),
httputil.WithJSONBody(c, param),
)
}
// DeleteEmoji requires MANAGE_EMOJIS.
func (c *Client) DeleteEmoji(guildID, emojiID discord.Snowflake) error {
return c.FastRequest("DELETE",
EndpointGuilds+guildID.String()+"/emojis/"+emojiID.String())
}

View file

@ -1,3 +1,68 @@
package api
import (
"github.com/diamondburned/arikawa/discord" // for clarity
d "github.com/diamondburned/arikawa/discord"
"github.com/diamondburned/arikawa/httputil"
)
const EndpointGuilds = Endpoint + "guilds/"
// https://discordapp.com/developers/docs/resources/guild#create-guild-json-params
type CreateGuildData struct {
Name string `json:"name"`
Region string `json:"region"`
Icon Image `json:"image"`
// package dc is just package discord
Verification d.Verification `json:"verification_level"`
Notification d.Notification `json:"default_message_notifications"`
ExplicitFilter d.ExplicitFilter `json:"explicit_content_filter"`
// [0] (First entry) is ALWAYS @everyone.
Roles []discord.Role `json:"roles"`
// Partial, id field is ignored. Usually only Name and Type are changed.
Channels []discord.Channel `json:"channels"`
}
func (c *Client) CreateGuild(data CreateGuildData) (*discord.Guild, error) {
var g *discord.Guild
return g, c.RequestJSON(&g, "POST", Endpoint+"guilds",
httputil.WithJSONBody(c, data))
}
func (c *Client) Guild(guildID discord.Snowflake) (*discord.Guild, error) {
var g *discord.Guild
return g, c.RequestJSON(&g, "GET", EndpointGuilds+guildID.String())
}
// https://discordapp.com/developers/docs/resources/guild#modify-guild-json-params
type ModifyGuildData struct {
Name string `json:"name,omitempty"`
Region string `json:"region,omitempty"`
Icon *Image `json:"image,omitempty"`
// package d is just package discord
Verification *d.Verification `json:"verification_level,omitempty"`
Notification *d.Notification `json:"default_message_notifications,omitempty"`
ExplicitFilter *d.ExplicitFilter `json:"explicit_content_filter,omitempty"`
AFKChannelID *d.Snowflake `json:"afk_channel_id,string,omitempty"`
AFKTimeout *d.Seconds `json:"afk_timeout,omitempty"`
OwnerID d.Snowflake `json:"owner_id,string,omitempty"`
Splash *Image `json:"splash,omitempty"`
Banner *Image `json:"banner,omitempty"`
SystemChannelID d.Snowflake `json:"system_channel_id,string,omitempty"`
}
func (c *Client) ModifyGuild(
guildID discord.Snowflake, data ModifyGuildData) (*discord.Guild, error) {
var g *discord.Guild
return g, c.RequestJSON(&g, "PATCH", EndpointGuilds+guildID.String(),
httputil.WithJSONBody(c, data))
}

123
api/image.go Normal file
View file

@ -0,0 +1,123 @@
package api
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"github.com/pkg/errors"
)
var ErrInvalidImageCT = errors.New("Unknown image content-type")
var ErrInvalidImageData = errors.New("Invalid image data")
type ErrImageTooLarge struct {
Size, Max int
}
func (err ErrImageTooLarge) Error() string {
return fmt.Sprintf("Image is %.02fkb, larger than %.02fkb",
float64(err.Size)/1000, float64(err.Max)/1000)
}
// Image wraps around the Data URI Scheme that Discord uses:
// https://discordapp.com/developers/docs/reference#image-data
type Image struct {
// ContentType is optional and will be automatically detected. However, it
// should always return "image/jpeg," "image/png" or "image/gif".
ContentType string
// Just raw content of the file.
Content []byte
// Utility fields, not used for encoding
MaxSize int // bytes
}
func DecodeImage(data []byte) (*Image, error) {
parts := bytes.SplitN(data, []byte{';'}, 2)
if len(parts) < 2 {
return nil, ErrInvalidImageData
}
if !bytes.HasPrefix(parts[0], []byte("data:")) {
return nil, errors.Wrap(ErrInvalidImageData, "invalid header")
}
if !bytes.HasPrefix(parts[1], []byte("base64,")) {
return nil, errors.Wrap(ErrInvalidImageData, "invalid base64")
}
var b64 = parts[1][len("base64,"):]
var img = Image{
ContentType: string(parts[0][len("data:"):]),
Content: make([]byte, base64.StdEncoding.DecodedLen(len(b64))),
}
base64.StdEncoding.Decode(img.Content, b64)
return &img, nil
}
func (i Image) Validate() error {
if i.MaxSize > 0 && len(i.Content) > i.MaxSize {
return ErrImageTooLarge{len(i.Content), i.MaxSize}
}
switch i.ContentType {
case "image/png", "image/jpeg", "image/gif":
return nil
default:
return ErrInvalidImageCT
}
}
func (i Image) Encode() ([]byte, error) {
if i.ContentType == "" {
var max = 512
if len(i.Content) < max {
max = len(i.Content)
}
i.ContentType = http.DetectContentType(i.Content[:max])
}
if err := i.Validate(); err != nil {
return nil, err
}
b64enc := make([]byte, base64.StdEncoding.EncodedLen(len(i.Content)))
base64.StdEncoding.Encode(b64enc, i.Content)
return bytes.Join([][]byte{
[]byte("data:"),
[]byte(i.ContentType),
[]byte(";base64,"),
b64enc,
}, nil), nil
}
var _ json.Marshaler = (*Image)(nil)
var _ json.Unmarshaler = (*Image)(nil)
func (i Image) MarshalJSON() ([]byte, error) {
b, err := i.Encode()
if err != nil {
return nil, err
}
return bytes.Join([][]byte{{'"'}, b, {'"'}}, nil), nil
}
func (i *Image) UnmarshalJSON(v []byte) error {
// Trim string
v = bytes.Trim(v, `"`)
img, err := DecodeImage(v)
if err != nil {
return err
}
*i = *img
return nil
}

View file

@ -16,21 +16,21 @@ type Channel struct {
Icon Hash `json:"icon,omitempty"`
// Direct Messaging fields
DMOwnerID Snowflake `json:"owner_id,omitempty"`
DMOwnerID Snowflake `json:"owner_id,string,omitempty"`
DMRecipients []User `json:"recipients,omitempty"`
// AppID of the group DM creator if it's bot-created
AppID Snowflake `json:"application_id,omitempty"`
AppID Snowflake `json:"application_id,string,omitempty"`
// ID of the category the channel is in, if any.
CategoryID Snowflake `json:"parent_id,omitempty"`
CategoryID Snowflake `json:"parent_id,string,omitempty"`
LastPinTime Timestamp `json:"last_pin_timestamp,omitempty"`
// Explicit permission overrides for members and roles.
Permissions []Overwrite `json:"permission_overwrites,omitempty"`
// ID of the last message, may not point to a valid one.
LastMessageID Snowflake `json:"last_message_id,omitempty"`
LastMessageID Snowflake `json:"last_message_id,string,omitempty"`
// Slow mode duration. Bots and people with "manage_messages" or
// "manage_channel" permissions are unaffected.
@ -54,10 +54,10 @@ const (
)
type Overwrite struct {
ID Snowflake `json:"id,omitempty"`
ID Snowflake `json:"id,string,omitempty"`
Type OverwriteType `json:"type"`
Allow uint64 `json:"allow"`
Deny uint64 `json:"deny"`
Allow Permissions `json:"allow"`
Deny Permissions `json:"deny"`
}
type OverwriteType string

View file

@ -3,7 +3,7 @@ package discord
import "strings"
type Emoji struct {
ID Snowflake `json:"id"` // 0 for Unicode emojis
ID Snowflake `json:"id,string"` // 0 for Unicode emojis
Name string `json:"name"`
// These fields are optional

View file

@ -1,5 +1,111 @@
package discord
type Guild struct{}
type Guild struct {
ID Snowflake `json:"id,string"`
Name string `json:"name"`
Icon Hash `json:"icon"`
Splash Hash `json:"splash,omitempty"` // server invite bg
type GuildMember struct{}
Owner bool `json:"owner,omitempty"` // self is owner
OwnerID Snowflake `json:"owner_id,string"`
Permissions Permissions `json:"permissions,omitempty"`
VoiceRegion string `json:"region"`
AFKChannelID Snowflake `json:"afk_channel_id,string,omitempty"`
AFKTimeout Seconds `json:"afk_timeout"`
Embeddable bool `json:"embed_enabled,omitempty"`
EmbedChannelID Snowflake `json:"embed_channel_id,string,omitempty"`
Verification Verification `json:"verification_level"`
Notification Notification `json:"default_message_notifications"`
ExplicitFilter ExplicitFilter `json:"explicit_content_filter"`
Roles []Role `json:"roles"`
Emojis []Emoji `json:"emojis"`
Features []GuildFeature `json:"guild_features"`
MFA MFALevel `json:"mfa"`
AppID Snowflake `json:"application_id,string,omitempty"`
Widget bool `json:"widget_enabled,omitempty"`
WidgetChannelID Snowflake `json:"widget_channel_id,string,omitempty"`
SystemChannelID Snowflake `json:"system_channel_id,string,omitempty"`
// GUILD_CREATE only.
Joined Timestamp `json:"timestamp,omitempty"`
Large bool `json:"large,omitempty"`
Unavailable bool `json:"unavailable,omitempty"`
MemberCount uint64 `json:"member_count,omitempty"`
VoiceStates []VoiceState `json:"voice_state,omitempty"`
Members []Member `json:"members,omitempty"`
Channels []Channel `json:"channel,omitempty"`
Presences []Presence `json:"presences,omitempty"`
// It's DefaultMaxPresences when MaxPresences is 0.
MaxPresences uint64 `json:"max_presences,omitempty"`
MaxMembers uint64 `json:"max_members,omitempty"`
VanityURLCode string `json:"vanity_url_code,omitempty"`
Description string `json:"description,omitempty"`
Banner Hash `json:"banner,omitempty"`
NitroBoost NitroBoost `json:"premium_tier"`
NitroBoosters uint64 `json:"premium_subscription_count,omitempty"`
// Defaults to en-US, only set if guild has DISCOVERABLE
PreferredLocale string `json:"preferred_locale"`
}
type Role struct {
ID Snowflake `json:"id,string"`
Name string `json:"name"`
Color Color `json:"color"`
Hoist bool `json:"hoist"` // if the role is separated
Position int `json:"position"`
Permissions Permissions `json:"permissions"`
Managed bool `json:"managed"`
Mentionable bool `json:"mentionable"`
}
type Presence struct {
User User `json:"user"`
RoleIDs []Snowflake `json:"roles"`
}
type VoiceState struct {
// GuildID isn't available from the Guild struct.
GuildID Snowflake `json:"guild_id,string"`
ChannelID Snowflake `json:"channel_id,string"`
UserID Snowflake `json:"user_id,string"`
Member *Member `json:"member,omitempty"`
SessionID string `json:"session_id"`
Deaf bool `json:"deaf"`
Mute bool `json:"mute"`
SelfDeaf bool `json:"self_deaf"`
SelfMute bool `json:"self_mute"`
SelfStream bool `json:"self_stream,omitempty"`
Suppress bool `json:"suppress"`
}
type Member struct {
User User `json:"user"`
Nick string `json:"nick,omitempty"`
RoleIDs []Snowflake `json:"roles"`
Joined Timestamp `json:"joined_at"`
BoostedSince Timestamp `json:"premium_since,omitempty"`
Deaf bool `json:"deaf"`
Mute bool `json:"mute"`
}

87
discord/guild_const.go Normal file
View file

@ -0,0 +1,87 @@
package discord
// Guild.MaxPresences is 5000 when it's 0. Seriously. The fucker who thought of
// this API thought it was also a good idea to return "null" instead of
// "5000." What the fucK? It has the same byte count, thus the same size.
// Sending the number over means it could be changed anytime and not force
// the developers to recheck. You could make the change right today and it
// would just work on all the clients. But no. IT'S FUCKING NULL!
const DefaultMaxPresences = 5000
type NitroBoost uint8
const (
NoNitroLevel NitroBoost = iota
NitroLevel1
NitroLevel2
NitroLevel3
)
type MFALevel uint8
const (
NoMFA MFALevel = iota
ElevatedMFA
)
type GuildFeature string
const (
// Guild has access to set an invite splash background
InviteSplash GuildFeature = "INVITE_SPLASH"
// Guild has access to set 384kbps bitrate in voice (previously VIP voice
// servers)
VIPRegions GuildFeature = "VIP_REGIONS"
// Guild has access to set a vanity URL
VanityURL GuildFeature = "VANITY_URL"
// Guild is verified
Verified GuildFeature = "VERIFIED"
// Guild is partnered
Partnered GuildFeature = "PARTNERED"
// Guild is public
Public GuildFeature = "PUBLIC"
// Guild has access to use commerce features (i.e. create store channels)
Commerce GuildFeature = "COMMERCE"
// Guild has access to create news channels
News GuildFeature = "NEWS"
// Guild is able to be discovered in the directory
Discoverable GuildFeature = "DISCOVERABLE"
// Guild is able to be featured in the directory
Featurable GuildFeature = "FEATURABLE"
// Guild has access to set an animated guild icon
AnimatedIcon GuildFeature = "ANIMATED_ICON"
// Guild has access to set a guild banner image
Banner GuildFeature = "BANNER"
)
type ExplicitFilter uint8
const (
NoContentFilter ExplicitFilter = iota
MembersWithoutRoles
AllMembers
)
type Notification uint8
const (
AllMessages Notification = iota
OnlyMentions
)
type Verification uint8
const (
NoVerification Verification = iota
// LowVerification requires a verified email
LowVerification
// MediumVerification requires the user be registered for at least 5
// minutes.
MediumVerification
// HighVerification requires the member be in the server for more than 10
// minutes.
HighVerification
// VeryHighVerification requires the member to have a verified phone
// number.
VeryHighVerification
)

View file

@ -1,10 +1,10 @@
package discord
type Message struct {
ID Snowflake `json:"id"`
ID Snowflake `json:"id,string"`
Type MessageType `json:"type"`
ChannelID Snowflake `json:"channel_id"`
GuildID Snowflake `json:"guild_id,omitempty"`
ChannelID Snowflake `json:"channel_id,string"`
GuildID Snowflake `json:"guild_id,string,omitempty"`
// The author object follows the structure of the user object, but is only
// a valid user in the case where the message is generated by a user or bot
@ -16,7 +16,7 @@ type Message struct {
// The member object exists in MESSAGE_CREATE and MESSAGE_UPDATE
// events from text-based guild channels.
Member *GuildMember `json:"member,omitempty"`
Member *Member `json:"member,omitempty"`
Content string `json:"content"`
@ -45,7 +45,7 @@ type Message struct {
// Used for validating a message was sent
Nonce string `json:"nonce,omitempty"`
WebhookID Snowflake `json:"webhook_id,omitempty"`
WebhookID Snowflake `json:"webhook_id,string,omitempty"`
Activity *MessageActivity `json:"activity,omitempty"`
Application *MessageApplication `json:"application,omitempty"`
Reference *MessageReference `json:"message_reference,omitempty"`
@ -81,15 +81,15 @@ const (
)
type ChannelMention struct {
ChannelID Snowflake `json:"id"`
GuildID Snowflake `json:"guild_id"`
ChannelID Snowflake `json:"id,string"`
GuildID Snowflake `json:"guild_id,string"`
ChannelType ChannelType `json:"type"`
ChannelName string `json:"name"`
}
type GuildUser struct {
User
Member *GuildMember `json:"member,omitempty"`
Member *Member `json:"member,omitempty"`
}
//
@ -113,7 +113,7 @@ const (
//
type MessageApplication struct {
ID Snowflake `json:"id"`
ID Snowflake `json:"id,string"`
CoverID string `json:"cover_image,omitempty"`
Description string `json:"description"`
Icon string `json:"icon"`
@ -123,17 +123,17 @@ type MessageApplication struct {
//
type MessageReference struct {
ChannelID Snowflake `json:"channel_id"`
ChannelID Snowflake `json:"channel_id,string"`
// Field might not be provided
MessageID Snowflake `json:"message_id,omitempty"`
GuildID Snowflake `json:"guild_id,omitempty"`
MessageID Snowflake `json:"message_id,string,omitempty"`
GuildID Snowflake `json:"guild_id,string,omitempty"`
}
//
type Attachment struct {
ID Snowflake `json:"id"`
ID Snowflake `json:"id,string"`
Filename string `json:"filename"`
Size uint64 `json:"size"`

181
discord/permission.go Normal file
View file

@ -0,0 +1,181 @@
package discord
type Permissions uint64
const (
// Allows creation of instant invites
PermissionCreateInstantInvite Permissions = 1 << iota
// Allows kicking members
PermissionKickMembers
// Allows banning members
PermissionBanMembers
// Allows all permissions and bypasses channel permission overwrites
PermissionAdministrator
// Allows management and editing of channels
PermissionManageChannels
// Allows management and editing of the guild
PermissionManageGuild
// Allows for the addition of reactions to messages
PermissionAddReactions
// Allows for viewing of audit logs
PermissionViewAuditLog
// Allows for using priority speaker in a voice channel
PermissionPrioritySpeaker
// Allows the user to go live
PermissionStream
// Allows guild members to view a channel, which includes reading messages
// in text channels
PermissionViewChannel
// Allows for sending messages in a channel
PermissionSendMessages
// Allows for sending of /tts messages
PermissionSendTTSMessages
// Allows for deletion of other users messages
PermissionManageMessages
// Links sent by users with this permission will be auto-embedded
PermissionEmbedLinks
// Allows for uploading images and files
PermissionAttachFiles
// Allows for reading of message history
PermissionReadMessageHistory
// Allows for using the @everyone tag to notify all users in a channel,
// and the @here tag to notify all online users in a channel
PermissionMentionEveryone
// Allows the usage of custom emojis from other servers
PermissionUseExternalEmojis
_ // ?
// Allows for joining of a voice channel
PermissionConnect
// Allows for speaking in a voice channel
PermissionSpeak
// Allows for muting members in a voice channel
PermissionMuteMembers
// Allows for deafening of members in a voice channel
PermissionDeafenMembers
// Allows for moving of members between voice channels
PermissionMoveMembers
// Allows for using voice-activity-detection in a voice channel
PermissionUseVAD
// Allows for modification of own nickname
PermissionChangeNickname
// Allows for modification of other users nicknames
PermissionManageNicknames
// Allows management and editing of roles
PermissionManageRoles
// Allows management and editing of webhooks
PermissionManageWebhooks
// Allows management and editing of emojis
PermissionManageEmojis
PermissionAllText = 0 |
PermissionViewChannel |
PermissionSendMessages |
PermissionSendTTSMessages |
PermissionManageMessages |
PermissionEmbedLinks |
PermissionAttachFiles |
PermissionReadMessageHistory |
PermissionMentionEveryone
PermissionAllVoice = 0 |
PermissionConnect |
PermissionSpeak |
PermissionMuteMembers |
PermissionDeafenMembers |
PermissionMoveMembers |
PermissionUseVAD |
PermissionPrioritySpeaker
PermissionAllChannel = 0 |
PermissionAllText |
PermissionAllVoice |
PermissionCreateInstantInvite |
PermissionManageRoles |
PermissionManageChannels |
PermissionAddReactions |
PermissionViewAuditLog
PermissionAll = 0 |
PermissionAllChannel |
PermissionKickMembers |
PermissionBanMembers |
PermissionManageGuild |
PermissionAdministrator |
PermissionManageWebhooks |
PermissionManageEmojis
)
func (p Permissions) Has(perm Permissions) bool {
return (p & perm) == perm
}
func (p Permissions) Add(perm Permissions) Permissions {
return p | perm
}
func CalcOverwrites(guild Guild, channel Channel, member Member) Permissions {
if guild.OwnerID == member.User.ID {
return PermissionAll
}
var perm Permissions
for _, role := range guild.Roles {
if role.ID == guild.ID {
perm |= role.Permissions
break
}
}
for _, role := range guild.Roles {
for _, id := range member.RoleIDs {
if id == role.ID {
perm |= role.Permissions
break
}
}
}
if perm.Has(PermissionAdministrator) {
return PermissionAll
}
for _, overwrite := range channel.Permissions {
if overwrite.ID == guild.ID {
perm &= ^overwrite.Deny
perm |= overwrite.Allow
break
}
}
var deny, allow Permissions
for _, overwrite := range channel.Permissions {
for _, id := range member.RoleIDs {
if id == overwrite.ID && overwrite.Type == "role" {
deny |= overwrite.Deny
allow |= overwrite.Allow
break
}
}
}
perm &= ^deny
perm |= allow
for _, overwrite := range channel.Permissions {
if overwrite.ID == member.User.ID {
perm &= ^overwrite.Deny
perm |= overwrite.Allow
break
}
}
if perm.Has(PermissionAdministrator) {
return PermissionAll
}
return perm
}

View file

@ -1,6 +1,7 @@
package discord
import (
"bytes"
"strconv"
"time"
)
@ -13,6 +14,21 @@ func NewSnowflake(t time.Time) Snowflake {
return Snowflake(TimeToDiscordEpoch(t) << 22)
}
func (s *Snowflake) UnmarshalJSON(v []byte) error {
v = bytes.Trim(v, `"`)
u, err := strconv.ParseUint(string(v), 10, 64)
if err != nil {
return err
}
*s = Snowflake(u)
return nil
}
func (s *Snowflake) MarshalJSON() ([]byte, error) {
return []byte(`"` + strconv.FormatUint(uint64(*s), 10) + `"`), nil
}
func (s Snowflake) String() string {
return strconv.FormatUint(uint64(s), 10)
}

View file

@ -1,7 +1,7 @@
package discord
type User struct {
UserID Snowflake `json:"id"`
ID Snowflake `json:"id,string"`
Username string `json:"username"`
Discriminator string `json:"discriminator"`
Avatar Hash `json:"avatar"`
@ -18,7 +18,7 @@ type User struct {
Email string `json:"email,omitempty"`
Flags UserFlags `json:"flags,omitempty"`
Nitro Nitro `json:"premium_type,omitempty"`
Nitro UserNitro `json:"premium_type,omitempty"`
}
type UserFlags uint16
@ -38,10 +38,10 @@ const (
System
)
type Nitro uint8
type UserNitro uint8
const (
NoNitro Nitro = iota
NoUserNitro UserNitro = iota
NitroClassic
NitroFull
)