arikawa/api/member.go

332 lines
10 KiB
Go
Raw Normal View History

2020-01-16 04:27:57 +00:00
package api
import (
"github.com/diamondburned/arikawa/discord"
"github.com/diamondburned/arikawa/utils/httputil"
"github.com/diamondburned/arikawa/utils/json/option"
2020-01-16 04:27:57 +00:00
)
const maxMemberFetchLimit = 1000
// Member returns a guild member object for the specified user.
func (c *Client) Member(guildID discord.GuildID, userID discord.UserID) (*discord.Member, error) {
2020-01-18 19:34:08 +00:00
var m *discord.Member
2020-05-12 02:05:08 +00:00
return m, c.RequestJSON(&m, "GET", EndpointGuilds+guildID.String()+"/members/"+userID.String())
2020-01-18 19:34:08 +00:00
}
2020-05-16 23:35:57 +00:00
// Members returns a list of members of the guild with the passed id. This
// method automatically paginates until it reaches the passed limit, or, if the
// limit is set to 0, has fetched all members in the guild.
2020-05-11 22:06:19 +00:00
//
2020-05-16 23:35:57 +00:00
// As the underlying endpoint has a maximum of 1000 members per request, at
// maximum a total of limit/1000 rounded up requests will be made, although
// they may be less if no more members are available.
2020-05-16 23:35:57 +00:00
//
// When fetching the members, those with the smallest ID will be fetched first.
func (c *Client) Members(guildID discord.GuildID, limit uint) ([]discord.Member, error) {
2020-05-16 23:35:57 +00:00
return c.MembersAfter(guildID, 0, limit)
}
// MembersAfter returns a list of members of the guild with the passed id. This
// method automatically paginates until it reaches the passed limit, or, if the
// limit is set to 0, has fetched all members with an id higher than after.
2020-05-16 23:35:57 +00:00
//
// As the underlying endpoint has a maximum of 1000 members per request, at
// maximum a total of limit/1000 rounded up requests will be made, although
// they may be less, if no more members are available.
func (c *Client) MembersAfter(
guildID discord.GuildID, after discord.UserID, limit uint) ([]discord.Member, error) {
2020-05-16 23:35:57 +00:00
mems := make([]discord.Member, 0, limit)
2020-01-16 04:27:57 +00:00
fetch := uint(maxMemberFetchLimit)
2020-01-16 04:27:57 +00:00
2020-05-16 23:35:57 +00:00
unlimited := limit == 0
2020-05-11 22:06:19 +00:00
for limit > 0 || unlimited {
// Only fetch as much as we need. Since limit gradually decreases,
// we only need to fetch min(fetch, limit).
2020-05-16 23:35:57 +00:00
if limit > 0 {
if fetch > limit {
fetch = limit
2020-01-18 19:34:08 +00:00
}
2020-05-16 23:35:57 +00:00
limit -= fetch
2020-01-16 04:27:57 +00:00
}
2020-05-16 23:35:57 +00:00
m, err := c.membersAfter(guildID, after, fetch)
2020-01-16 04:27:57 +00:00
if err != nil {
return mems, err
}
mems = append(mems, m...)
2020-05-16 23:35:57 +00:00
// There aren't any to fetch, even if this is less than limit.
if len(m) < maxMemberFetchLimit {
2020-01-16 04:27:57 +00:00
break
}
2020-05-22 22:59:27 +00:00
after = mems[len(mems)-1].User.ID
2020-01-16 04:27:57 +00:00
}
if len(mems) == 0 {
return nil, nil
}
2020-01-16 04:27:57 +00:00
return mems, nil
}
2020-05-16 23:35:57 +00:00
func (c *Client) membersAfter(
guildID discord.GuildID, after discord.UserID, limit uint) ([]discord.Member, error) {
2020-01-16 04:27:57 +00:00
2020-05-11 22:06:19 +00:00
switch {
case limit == 0:
limit = 0
case limit > 1000:
2020-01-16 04:27:57 +00:00
limit = 1000
}
var param struct {
After discord.UserID `schema:"after,omitempty"`
Limit uint `schema:"limit"`
2020-01-16 04:27:57 +00:00
}
param.Limit = limit
param.After = after
var mems []discord.Member
return mems, c.RequestJSON(
&mems, "GET",
EndpointGuilds+guildID.String()+"/members",
httputil.WithSchema(c, param),
)
}
2020-05-11 22:06:19 +00:00
// https://discord.com/developers/docs/resources/guild#add-guild-member-json-params
type AddMemberData struct {
// Token is an oauth2 access token granted with the guilds.join to the
// bot's application for the user you want to add to the guild.
Token string `json:"access_token"`
// Nick is the value to set users nickname to.
//
// Requires MANAGE_NICKNAMES.
Nick option.String `json:"nick,omitempty"`
2020-05-11 22:06:19 +00:00
// Roles is an array of role ids the member is assigned.
//
// Requires MANAGE_ROLES.
Roles *[]discord.RoleID `json:"roles,omitempty"`
2020-05-11 22:06:19 +00:00
// Mute specifies whether the user is muted in voice channels.
//
// Requires MUTE_MEMBERS.
Mute option.Bool `json:"mute,omitempty"`
// Deaf specifies whether the user is deafened in voice channels.
//
// Requires DEAFEN_MEMBERS.
Deaf option.Bool `json:"deaf,omitempty"`
2020-01-16 04:27:57 +00:00
}
2020-05-11 22:06:19 +00:00
// AddMember adds a user to the guild, provided you have a valid oauth2 access
// token for the user with the guilds.join scope. Returns a 201 Created with
// the guild member as the body, or 204 No Content if the user is already a
// member of the guild.
//
// Fires a Guild Member Add Gateway event.
//
// The Authorization header must be a Bot token (belonging to the same
// application used for authorization), and the bot must be a member of the
// guild with CREATE_INSTANT_INVITE permission.
2020-01-16 04:27:57 +00:00
func (c *Client) AddMember(
guildID discord.GuildID, userID discord.UserID, data AddMemberData) (*discord.Member, error) {
2020-01-16 04:27:57 +00:00
var mem *discord.Member
return mem, c.RequestJSON(
&mem, "PUT",
EndpointGuilds+guildID.String()+"/members/"+userID.String(),
2020-05-11 22:06:19 +00:00
httputil.WithJSONBody(data),
2020-01-16 04:27:57 +00:00
)
}
2020-05-11 22:06:19 +00:00
// https://discord.com/developers/docs/resources/guild#add-guild-member-json-params
type ModifyMemberData struct {
// Nick is the value to set users nickname to.
//
// Requires MANAGE_NICKNAMES.
Nick option.String `json:"nick,omitempty"`
// Roles is an array of role ids the member is assigned.
//
// Requires MANAGE_ROLES.
Roles *[]discord.RoleID `json:"roles,omitempty"`
2020-05-11 22:06:19 +00:00
// Mute specifies whether the user is muted in voice channels.
//
// Requires MUTE_MEMBERS.
Mute option.Bool `json:"mute,omitempty"`
// Deaf specifies whether the user is deafened in voice channels.
//
// Requires DEAFEN_MEMBERS.
Deaf option.Bool `json:"deaf,omitempty"`
// Voice channel is the id of channel to move user to (if they are
// connected to voice).
//
// Requires MOVE_MEMBER
VoiceChannel discord.ChannelID `json:"channel_id,omitempty"`
2020-05-11 22:06:19 +00:00
}
// ModifyMember modifies attributes of a guild member. If the channel_id is set
// to null, this will force the target user to be disconnected from voice.
//
// Fires a Guild Member Update Gateway event.
func (c *Client) ModifyMember(guildID discord.GuildID, userID discord.UserID, data ModifyMemberData) error {
2020-01-16 04:27:57 +00:00
return c.FastRequest(
"PATCH",
EndpointGuilds+guildID.String()+"/members/"+userID.String(),
httputil.WithJSONBody(data),
2020-01-16 04:27:57 +00:00
)
}
2020-05-22 19:05:24 +00:00
// https://discord.com/developers/docs/resources/guild#get-guild-prune-count-query-string-params
type PruneCountData struct {
2020-07-12 01:51:01 +00:00
// Days is the number of days to count prune for (1 or more, default 7).
2020-05-22 19:05:24 +00:00
Days uint `schema:"days"`
// IncludedRoles are the role(s) to include.
IncludedRoles []discord.RoleID `schema:"include_roles,omitempty"`
2020-05-22 19:05:24 +00:00
}
2020-01-16 04:27:57 +00:00
// PruneCount returns the number of members that would be removed in a prune
2020-05-11 22:06:19 +00:00
// operation. Days must be 1 or more, default 7.
//
2020-05-22 19:05:24 +00:00
// By default, prune will not remove users with roles. You can optionally
// include specific roles in your prune by providing the IncludedRoles
// parameter. Any inactive user that has a subset of the provided role(s)
// will be counted in the prune and users with additional roles will not.
//
2020-05-11 22:06:19 +00:00
// Requires KICK_MEMBERS.
func (c *Client) PruneCount(guildID discord.GuildID, data PruneCountData) (uint, error) {
2020-05-22 19:05:24 +00:00
if data.Days == 0 {
data.Days = 7
2020-01-16 04:27:57 +00:00
}
var resp struct {
Pruned uint `json:"pruned"`
}
return resp.Pruned, c.RequestJSON(
&resp, "GET",
EndpointGuilds+guildID.String()+"/prune",
2020-05-22 19:05:24 +00:00
httputil.WithSchema(c, data),
2020-01-16 04:27:57 +00:00
)
}
2020-05-22 19:05:24 +00:00
// https://discord.com/developers/docs/resources/guild#begin-guild-prune-query-string-params
type PruneData struct {
2020-07-12 01:51:01 +00:00
// Days is the number of days to prune (1 or more, default 7).
2020-05-22 19:05:24 +00:00
Days uint `schema:"days"`
// ReturnCount specifies whether 'pruned' is returned. Discouraged for
// large guilds.
ReturnCount bool `schema:"compute_prune_count"`
// IncludedRoles are the role(s) to include.
IncludedRoles []discord.RoleID `schema:"include_roles,omitempty"`
2020-05-12 03:15:50 +00:00
}
2020-05-22 19:05:24 +00:00
// Prune begins a prune. Days must be 1 or more, default 7.
//
// By default, prune will not remove users with roles. You can optionally
// include specific roles in your prune by providing the IncludedRoles
// parameter. Any inactive user that has a subset of the provided role(s)
// will be included in the prune and users with additional roles will not.
2020-05-11 22:06:19 +00:00
//
// Requires KICK_MEMBERS.
2020-05-22 19:05:24 +00:00
// Fires multiple Guild Member Remove Gateway events.
func (c *Client) Prune(guildID discord.GuildID, data PruneData) (uint, error) {
2020-05-22 19:05:24 +00:00
if data.Days == 0 {
data.Days = 7
2020-01-16 04:27:57 +00:00
}
var resp struct {
Pruned uint `json:"pruned"`
}
return resp.Pruned, c.RequestJSON(
&resp, "POST",
EndpointGuilds+guildID.String()+"/prune",
2020-05-22 19:05:24 +00:00
httputil.WithSchema(c, data),
2020-01-16 04:27:57 +00:00
)
}
2020-05-11 22:06:19 +00:00
// Kick removes a member from a guild.
//
// Requires KICK_MEMBERS permission.
// Fires a Guild Member Remove Gateway event.
func (c *Client) Kick(guildID discord.GuildID, userID discord.UserID) error {
2020-08-22 16:51:10 +00:00
return c.KickWithReason(guildID, userID, "")
}
// KickWithReason removes a member from a guild.
// The reason, if non-empty, will be displayed in the audit log of the guild.
//
// Requires KICK_MEMBERS permission.
// Fires a Guild Member Remove Gateway event.
func (c *Client) KickWithReason(
guildID discord.GuildID, userID discord.UserID, reason string) error {
var data struct {
Reason string `schema:"reason,omitempty"`
}
data.Reason = reason
2020-05-12 02:05:08 +00:00
return c.FastRequest(
"DELETE",
EndpointGuilds+guildID.String()+"/members/"+userID.String(),
2020-08-22 16:51:10 +00:00
httputil.WithSchema(c, data),
2020-05-12 02:05:08 +00:00
)
2020-01-16 04:27:57 +00:00
}
2020-05-11 22:06:19 +00:00
// Bans returns a list of ban objects for the users banned from this guild.
//
// Requires the BAN_MEMBERS permission.
func (c *Client) Bans(guildID discord.GuildID) ([]discord.Ban, error) {
2020-01-16 04:27:57 +00:00
var bans []discord.Ban
2020-05-12 02:05:08 +00:00
return bans, c.RequestJSON(
&bans, "GET",
EndpointGuilds+guildID.String()+"/bans",
)
2020-01-16 04:27:57 +00:00
}
2020-05-11 22:06:19 +00:00
// GetBan returns a ban object for the given user.
//
// Requires the BAN_MEMBERS permission.
func (c *Client) GetBan(guildID discord.GuildID, userID discord.UserID) (*discord.Ban, error) {
2020-01-16 04:27:57 +00:00
var ban *discord.Ban
2020-05-12 02:05:08 +00:00
return ban, c.RequestJSON(
&ban, "GET",
EndpointGuilds+guildID.String()+"/bans/"+userID.String(),
)
2020-01-16 04:27:57 +00:00
}
2020-05-11 22:06:19 +00:00
// https://discord.com/developers/docs/resources/guild#create-guild-ban-query-string-params
type BanData struct {
// DeleteDays is the number of days to delete messages for (0-7).
DeleteDays option.Uint `schema:"delete_message_days,omitempty"`
// Reason is the reason for the ban.
Reason option.String `schema:"reason,omitempty"`
}
2020-01-16 04:27:57 +00:00
2020-05-11 22:06:19 +00:00
// Ban creates a guild ban, and optionally delete previous messages sent by the
// banned user.
//
// Requires the BAN_MEMBERS permission.
func (c *Client) Ban(guildID discord.GuildID, userID discord.UserID, data BanData) error {
2020-01-16 04:27:57 +00:00
return c.FastRequest(
"PUT",
EndpointGuilds+guildID.String()+"/bans/"+userID.String(),
2020-05-11 22:06:19 +00:00
httputil.WithSchema(c, data),
2020-01-16 04:27:57 +00:00
)
}
2020-05-11 22:06:19 +00:00
// Unban removes the ban for a user.
//
// Requires the BAN_MEMBERS permissions.
// Fires a Guild Ban Remove Gateway event.
func (c *Client) Unban(guildID discord.GuildID, userID discord.UserID) error {
return c.FastRequest("DELETE", EndpointGuilds+guildID.String()+"/bans/"+userID.String())
2020-01-16 04:27:57 +00:00
}