github.com/diamondburned/arikawa/v2@v2.1.0/api/member.go (about)

     1  package api
     2  
     3  import (
     4  	"github.com/diamondburned/arikawa/v2/discord"
     5  	"github.com/diamondburned/arikawa/v2/internal/intmath"
     6  	"github.com/diamondburned/arikawa/v2/utils/httputil"
     7  	"github.com/diamondburned/arikawa/v2/utils/json/option"
     8  )
     9  
    10  const MaxMemberFetchLimit = 1000
    11  
    12  // Member returns a guild member object for the specified user.
    13  func (c *Client) Member(guildID discord.GuildID, userID discord.UserID) (*discord.Member, error) {
    14  	var m *discord.Member
    15  	return m, c.RequestJSON(&m, "GET", EndpointGuilds+guildID.String()+"/members/"+userID.String())
    16  }
    17  
    18  // Members returns a list of members of the guild with the passed id. This
    19  // method automatically paginates until it reaches the passed limit, or, if the
    20  // limit is set to 0, has fetched all members in the guild.
    21  //
    22  // As the underlying endpoint has a maximum of 1000 members per request, at
    23  // maximum a total of limit/1000 rounded up requests will be made, although
    24  // they may be less if no more members are available.
    25  //
    26  // When fetching the members, those with the smallest ID will be fetched first.
    27  func (c *Client) Members(guildID discord.GuildID, limit uint) ([]discord.Member, error) {
    28  	return c.MembersAfter(guildID, 0, limit)
    29  }
    30  
    31  // MembersAfter returns a list of members of the guild with the passed id. This
    32  // method automatically paginates until it reaches the passed limit, or, if the
    33  // limit is set to 0, has fetched all members with an id higher than after.
    34  //
    35  // As the underlying endpoint has a maximum of 1000 members per request, at
    36  // maximum a total of limit/1000 rounded up requests will be made, although
    37  // they may be less, if no more members are available.
    38  func (c *Client) MembersAfter(
    39  	guildID discord.GuildID, after discord.UserID, limit uint) ([]discord.Member, error) {
    40  
    41  	mems := make([]discord.Member, 0, limit)
    42  
    43  	fetch := uint(MaxMemberFetchLimit)
    44  
    45  	unlimited := limit == 0
    46  
    47  	for limit > 0 || unlimited {
    48  		// Only fetch as much as we need. Since limit gradually decreases,
    49  		// we only need to fetch intmath.Min(fetch, limit).
    50  		if limit > 0 {
    51  			fetch = uint(intmath.Min(MaxMemberFetchLimit, int(limit)))
    52  			limit -= fetch
    53  		}
    54  
    55  		m, err := c.membersAfter(guildID, after, fetch)
    56  		if err != nil {
    57  			return mems, err
    58  		}
    59  		mems = append(mems, m...)
    60  
    61  		// There aren't any to fetch, even if this is less than limit.
    62  		if len(m) < MaxMemberFetchLimit {
    63  			break
    64  		}
    65  
    66  		after = mems[len(mems)-1].User.ID
    67  	}
    68  
    69  	if len(mems) == 0 {
    70  		return nil, nil
    71  	}
    72  
    73  	return mems, nil
    74  }
    75  
    76  func (c *Client) membersAfter(
    77  	guildID discord.GuildID, after discord.UserID, limit uint) ([]discord.Member, error) {
    78  
    79  	switch {
    80  	case limit == 0:
    81  		limit = 0
    82  	case limit > 1000:
    83  		limit = 1000
    84  	}
    85  
    86  	var param struct {
    87  		After discord.UserID `schema:"after,omitempty"`
    88  		Limit uint           `schema:"limit"`
    89  	}
    90  
    91  	param.Limit = limit
    92  	param.After = after
    93  
    94  	var mems []discord.Member
    95  	return mems, c.RequestJSON(
    96  		&mems, "GET",
    97  		EndpointGuilds+guildID.String()+"/members",
    98  		httputil.WithSchema(c, param),
    99  	)
   100  }
   101  
   102  // https://discord.com/developers/docs/resources/guild#add-guild-member-json-params
   103  type AddMemberData struct {
   104  	// Token is an oauth2 access token granted with the guilds.join to the
   105  	// bot's application for the user you want to add to the guild.
   106  	Token string `json:"access_token"`
   107  	// Nick is the value to set users nickname to.
   108  	//
   109  	// Requires MANAGE_NICKNAMES.
   110  	Nick option.String `json:"nick,omitempty"`
   111  	// Roles is an array of role ids the member is assigned.
   112  	//
   113  	// Requires MANAGE_ROLES.
   114  	Roles *[]discord.RoleID `json:"roles,omitempty"`
   115  	// Mute specifies whether the user is muted in voice channels.
   116  	//
   117  	// Requires MUTE_MEMBERS.
   118  	Mute option.Bool `json:"mute,omitempty"`
   119  	// Deaf specifies whether the user is deafened in voice channels.
   120  	//
   121  	// Requires DEAFEN_MEMBERS.
   122  	Deaf option.Bool `json:"deaf,omitempty"`
   123  }
   124  
   125  // AddMember adds a user to the guild, provided you have a valid oauth2 access
   126  // token for the user with the guilds.join scope. Returns a 201 Created with
   127  // the guild member as the body, or 204 No Content if the user is already a
   128  // member of the guild.
   129  //
   130  // Fires a Guild Member Add Gateway event.
   131  //
   132  // The Authorization header must be a Bot token (belonging to the same
   133  // application used for authorization), and the bot must be a member of the
   134  // guild with CREATE_INSTANT_INVITE permission.
   135  func (c *Client) AddMember(
   136  	guildID discord.GuildID, userID discord.UserID, data AddMemberData) (*discord.Member, error) {
   137  	var mem *discord.Member
   138  	return mem, c.RequestJSON(
   139  		&mem, "PUT",
   140  		EndpointGuilds+guildID.String()+"/members/"+userID.String(),
   141  		httputil.WithJSONBody(data),
   142  	)
   143  }
   144  
   145  // https://discord.com/developers/docs/resources/guild#add-guild-member-json-params
   146  type ModifyMemberData struct {
   147  	// Nick is the value to set users nickname to.
   148  	//
   149  	// Requires MANAGE_NICKNAMES.
   150  	Nick option.String `json:"nick,omitempty"`
   151  	// Roles is an array of role ids the member is assigned.
   152  	//
   153  	// Requires MANAGE_ROLES.
   154  	Roles *[]discord.RoleID `json:"roles,omitempty"`
   155  	// Mute specifies whether the user is muted in voice channels.
   156  	//
   157  	// Requires MUTE_MEMBERS.
   158  	Mute option.Bool `json:"mute,omitempty"`
   159  	// Deaf specifies whether the user is deafened in voice channels.
   160  	//
   161  	// Requires DEAFEN_MEMBERS.
   162  	Deaf option.Bool `json:"deaf,omitempty"`
   163  
   164  	// Voice channel is the id of channel to move user to (if they are
   165  	// connected to voice).
   166  	//
   167  	// Requires MOVE_MEMBER
   168  	VoiceChannel discord.ChannelID `json:"channel_id,omitempty"`
   169  }
   170  
   171  // ModifyMember modifies attributes of a guild member. If the channel_id is set
   172  // to null, this will force the target user to be disconnected from voice.
   173  //
   174  // Fires a Guild Member Update Gateway event.
   175  func (c *Client) ModifyMember(guildID discord.GuildID, userID discord.UserID, data ModifyMemberData) error {
   176  
   177  	return c.FastRequest(
   178  		"PATCH",
   179  		EndpointGuilds+guildID.String()+"/members/"+userID.String(),
   180  		httputil.WithJSONBody(data),
   181  	)
   182  }
   183  
   184  // https://discord.com/developers/docs/resources/guild#get-guild-prune-count-query-string-params
   185  type PruneCountData struct {
   186  	// Days is the number of days to count prune for (1 or more, default 7).
   187  	Days uint `schema:"days"`
   188  	// IncludedRoles are the role(s) to include.
   189  	IncludedRoles []discord.RoleID `schema:"include_roles,omitempty"`
   190  }
   191  
   192  // PruneCount returns the number of members that would be removed in a prune
   193  // operation. Days must be 1 or more, default 7.
   194  //
   195  // By default, prune will not remove users with roles. You can optionally
   196  // include specific roles in your prune by providing the IncludedRoles
   197  // parameter. Any inactive user that has a subset of the provided role(s)
   198  // will be counted in the prune and users with additional roles will not.
   199  //
   200  // Requires KICK_MEMBERS.
   201  func (c *Client) PruneCount(guildID discord.GuildID, data PruneCountData) (uint, error) {
   202  	if data.Days == 0 {
   203  		data.Days = 7
   204  	}
   205  
   206  	var resp struct {
   207  		Pruned uint `json:"pruned"`
   208  	}
   209  
   210  	return resp.Pruned, c.RequestJSON(
   211  		&resp, "GET",
   212  		EndpointGuilds+guildID.String()+"/prune",
   213  		httputil.WithSchema(c, data),
   214  	)
   215  }
   216  
   217  // https://discord.com/developers/docs/resources/guild#begin-guild-prune-query-string-params
   218  type PruneData struct {
   219  	// Days is the number of days to prune (1 or more, default 7).
   220  	Days uint `schema:"days"`
   221  	// ReturnCount specifies whether 'pruned' is returned. Discouraged for
   222  	// large guilds.
   223  	ReturnCount bool `schema:"compute_prune_count"`
   224  	// IncludedRoles are the role(s) to include.
   225  	IncludedRoles []discord.RoleID `schema:"include_roles,omitempty"`
   226  }
   227  
   228  // Prune begins a prune. Days must be 1 or more, default 7.
   229  //
   230  // By default, prune will not remove users with roles. You can optionally
   231  // include specific roles in your prune by providing the IncludedRoles
   232  // parameter. Any inactive user that has a subset of the provided role(s)
   233  // will be included in the prune and users with additional roles will not.
   234  //
   235  // Requires KICK_MEMBERS.
   236  // Fires multiple Guild Member Remove Gateway events.
   237  func (c *Client) Prune(guildID discord.GuildID, data PruneData) (uint, error) {
   238  	if data.Days == 0 {
   239  		data.Days = 7
   240  	}
   241  
   242  	var resp struct {
   243  		Pruned uint `json:"pruned"`
   244  	}
   245  
   246  	return resp.Pruned, c.RequestJSON(
   247  		&resp, "POST",
   248  		EndpointGuilds+guildID.String()+"/prune",
   249  		httputil.WithSchema(c, data),
   250  	)
   251  }
   252  
   253  // Kick removes a member from a guild.
   254  //
   255  // Requires KICK_MEMBERS permission.
   256  // Fires a Guild Member Remove Gateway event.
   257  func (c *Client) Kick(guildID discord.GuildID, userID discord.UserID) error {
   258  	return c.KickWithReason(guildID, userID, "")
   259  }
   260  
   261  // KickWithReason removes a member from a guild.
   262  // The reason, if non-empty, will be displayed in the audit log of the guild.
   263  //
   264  // Requires KICK_MEMBERS permission.
   265  // Fires a Guild Member Remove Gateway event.
   266  func (c *Client) KickWithReason(
   267  	guildID discord.GuildID, userID discord.UserID, reason string) error {
   268  
   269  	var data struct {
   270  		Reason string `schema:"reason,omitempty"`
   271  	}
   272  
   273  	data.Reason = reason
   274  
   275  	return c.FastRequest(
   276  		"DELETE",
   277  		EndpointGuilds+guildID.String()+"/members/"+userID.String(),
   278  		httputil.WithSchema(c, data),
   279  	)
   280  }
   281  
   282  // Bans returns a list of ban objects for the users banned from this guild.
   283  //
   284  // Requires the BAN_MEMBERS permission.
   285  func (c *Client) Bans(guildID discord.GuildID) ([]discord.Ban, error) {
   286  	var bans []discord.Ban
   287  	return bans, c.RequestJSON(
   288  		&bans, "GET",
   289  		EndpointGuilds+guildID.String()+"/bans",
   290  	)
   291  }
   292  
   293  // GetBan returns a ban object for the given user.
   294  //
   295  // Requires the BAN_MEMBERS permission.
   296  func (c *Client) GetBan(guildID discord.GuildID, userID discord.UserID) (*discord.Ban, error) {
   297  	var ban *discord.Ban
   298  	return ban, c.RequestJSON(
   299  		&ban, "GET",
   300  		EndpointGuilds+guildID.String()+"/bans/"+userID.String(),
   301  	)
   302  }
   303  
   304  // https://discord.com/developers/docs/resources/guild#create-guild-ban-query-string-params
   305  type BanData struct {
   306  	// DeleteDays is the number of days to delete messages for (0-7).
   307  	DeleteDays option.Uint `schema:"delete_message_days,omitempty"`
   308  	// Reason is the reason for the ban.
   309  	Reason option.String `schema:"reason,omitempty"`
   310  }
   311  
   312  // Ban creates a guild ban, and optionally delete previous messages sent by the
   313  // banned user.
   314  //
   315  // Requires the BAN_MEMBERS permission.
   316  func (c *Client) Ban(guildID discord.GuildID, userID discord.UserID, data BanData) error {
   317  	return c.FastRequest(
   318  		"PUT",
   319  		EndpointGuilds+guildID.String()+"/bans/"+userID.String(),
   320  		httputil.WithSchema(c, data),
   321  	)
   322  }
   323  
   324  // Unban removes the ban for a user.
   325  //
   326  // Requires the BAN_MEMBERS permissions.
   327  // Fires a Guild Ban Remove Gateway event.
   328  func (c *Client) Unban(guildID discord.GuildID, userID discord.UserID) error {
   329  	return c.FastRequest("DELETE", EndpointGuilds+guildID.String()+"/bans/"+userID.String())
   330  }