github.com/diamondburned/arikawa@v1.3.14/api/member.go (about)

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