public async Task RoleMenu(CommandContext ctx, string message, string emojis, [RemainingText] params DiscordRole[] roles) { var converter = (IArgumentConverter <DiscordEmoji>) new DiscordEmojiConverter(); var split = emojis.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); var emojiArray = new DiscordEmoji[roles.Length]; if (split.Length < roles.Length) { throw new ArgumentOutOfRangeException(nameof(emojis), "You don't have enough emojis!"); } if (roles.Length > 25) { throw new ArgumentOutOfRangeException(nameof(roles), "You can only have up to 25 roles per role menu!"); } for (var i = 0; i < roles.Length; i++) { var e = await converter.ConvertAsync(split[i], ctx); if (!e.HasValue) { throw new ArgumentException($"I couldn't parse {split[i]}"); } emojiArray[i] = e.Value; } var unavailable = emojiArray.Where(e => !e.IsAvailable && e.Id != 0); if (unavailable.Any()) { throw new ArgumentException($"One or more emojis is from a server I'm not in!\nNames: {string.Join(", ", unavailable.Select(u => u.GetDiscordName()))}"); } var buttons = new List <DiscordComponent>(5); var chnk = roles.Zip(emojiArray).Chunk(5).OrderBy(l => l.Count).ToList(); var builder = new DiscordMessageBuilder() .WithContent(message.Replace("\\n", "\n") + $"\n{string.Join('\n', chnk.SelectMany(c => c).Select(p => $"{p.Second} -> {p.First.Mention}"))}") .WithAllowedMentions(Mentions.None); foreach (var chunklist in chnk) { foreach (var pair in chunklist) { if (pair.First.Position >= ctx.Guild.CurrentMember.Hierarchy) { throw new InvalidOperationException("Cannot assign role higher or equal to my own role!"); } if (pair.First.Position > ctx.Member.Hierarchy) { throw new InvalidOperationException("Cannot assign role higher than your own!"); } var e = new DiscordComponentEmoji(pair.Second.Id); var b = new DiscordButtonComponent(ButtonStyle.Success, $"{pair.First.Mention}", "", emoji: e); buttons.Add(b); } builder.AddComponents(buttons.ToArray()); buttons.Clear(); } await builder.SendAsync(ctx.Channel); }