Merge pull request #255 from dev-kittens/feat/group-random
Add random command for groups
This commit is contained in:
		@@ -46,7 +46,7 @@ namespace PluralKit.Bot
 | 
			
		||||
        public static Command MemberDisplayName = new Command("member displayname", "member <member> displayname [display name]", "Changes a member's display name");
 | 
			
		||||
        public static Command MemberServerName = new Command("member servername", "member <member> servername [server name]", "Changes a member's display name in the current server");
 | 
			
		||||
        public static Command MemberKeepProxy = new Command("member keepproxy", "member <member> keepproxy [on|off]", "Sets whether to include a member's proxy tags when proxying");
 | 
			
		||||
        public static Command MemberRandom = new Command("random", "random", "Looks up a random member from your system");
 | 
			
		||||
        public static Command MemberRandom = new Command("random", "random", "Shows the info card of a randomly selected member in your system.");
 | 
			
		||||
        public static Command MemberPrivacy = new Command("member privacy", "member <member> privacy <name|description|birthday|pronouns|metadata|visibility|all> <public|private>", "Changes a members's privacy settings");
 | 
			
		||||
        public static Command GroupInfo = new Command("group", "group <name>", "Looks up information about a group");
 | 
			
		||||
        public static Command GroupNew = new Command("group new", "group new <name>", "Creates a new group");
 | 
			
		||||
@@ -60,6 +60,8 @@ namespace PluralKit.Bot
 | 
			
		||||
        public static Command GroupPrivacy = new Command("group privacy", "group <group> privacy <description|icon|visibility|all> <public|private>", "Changes a group's privacy settings");
 | 
			
		||||
        public static Command GroupIcon = new Command("group icon", "group <group> icon [url|@mention]", "Changes a group's icon");
 | 
			
		||||
        public static Command GroupDelete = new Command("group delete", "group <group> delete", "Deletes a group");
 | 
			
		||||
        public static Command GroupMemberRandom = new Command("group random", "group <group> random", "Shows the info card of a randomly selected member in a group.");
 | 
			
		||||
        public static Command GroupRandom = new Command("random", "random group", "Shows the info card of a randomly selected group in your system.");
 | 
			
		||||
        public static Command Switch = new Command("switch", "switch <member> [member 2] [member 3...]", "Registers a switch");
 | 
			
		||||
        public static Command SwitchOut = new Command("switch out", "switch out", "Registers a switch with no members");
 | 
			
		||||
        public static Command SwitchMove = new Command("switch move", "switch move <date/time>", "Moves the latest switch in time");
 | 
			
		||||
@@ -105,7 +107,7 @@ namespace PluralKit.Bot
 | 
			
		||||
        public static Command[] GroupCommandsTargeted =
 | 
			
		||||
        {
 | 
			
		||||
            GroupInfo, GroupAdd, GroupRemove, GroupMemberList, GroupRename, GroupDesc, GroupIcon, GroupPrivacy,
 | 
			
		||||
            GroupDelete
 | 
			
		||||
            GroupDelete, GroupMemberRandom
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        public static Command[] SwitchCommands = {Switch, SwitchOut, SwitchMove, SwitchDelete, SwitchDeleteAll};
 | 
			
		||||
@@ -196,7 +198,10 @@ namespace PluralKit.Bot
 | 
			
		||||
            if (ctx.Match("permcheck"))
 | 
			
		||||
                return ctx.Execute<Misc>(PermCheck, m => m.PermCheckGuild(ctx));
 | 
			
		||||
            if (ctx.Match("random", "r"))
 | 
			
		||||
                return ctx.Execute<Member>(MemberRandom, m => m.MemberRandom(ctx));
 | 
			
		||||
                if (ctx.Match("group", "g") || ctx.MatchFlag("group", "g"))
 | 
			
		||||
                return ctx.Execute<Random>(GroupRandom, r => r.Group(ctx));
 | 
			
		||||
            else
 | 
			
		||||
                return ctx.Execute<Random>(MemberRandom, m => m.Member(ctx));
 | 
			
		||||
 | 
			
		||||
            // remove compiler warning
 | 
			
		||||
            return ctx.Reply(
 | 
			
		||||
@@ -382,6 +387,8 @@ namespace PluralKit.Bot
 | 
			
		||||
                    await ctx.Execute<Groups>(GroupRemove, g => g.AddRemoveMembers(ctx, target, Groups.AddRemoveOperation.Remove));
 | 
			
		||||
                else if (ctx.Match("members", "list", "ms", "l"))
 | 
			
		||||
                    await ctx.Execute<Groups>(GroupMemberList, g => g.ListGroupMembers(ctx, target));
 | 
			
		||||
                else if (ctx.Match("random"))
 | 
			
		||||
                    await ctx.Execute<Random>(GroupMemberRandom, r => r.GroupMember(ctx, target));
 | 
			
		||||
                else if (ctx.Match("privacy"))
 | 
			
		||||
                    await ctx.Execute<Groups>(GroupPrivacy, g => g.GroupPrivacy(ctx, target, null));
 | 
			
		||||
                else if (ctx.Match("public", "pub"))
 | 
			
		||||
 
 | 
			
		||||
@@ -18,11 +18,13 @@ namespace PluralKit.Bot
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IDatabase _db;
 | 
			
		||||
        private readonly ModelRepository _repo;
 | 
			
		||||
        private readonly EmbedService _embeds;
 | 
			
		||||
 | 
			
		||||
        public Groups(IDatabase db, ModelRepository repo)
 | 
			
		||||
        public Groups(IDatabase db, ModelRepository repo, EmbedService embeds)
 | 
			
		||||
        {
 | 
			
		||||
            _db = db;
 | 
			
		||||
            _repo = repo;
 | 
			
		||||
            _embeds = embeds;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task CreateGroup(Context ctx)
 | 
			
		||||
@@ -280,38 +282,8 @@ namespace PluralKit.Bot
 | 
			
		||||
        public async Task ShowGroupCard(Context ctx, PKGroup target)
 | 
			
		||||
        {
 | 
			
		||||
            await using var conn = await _db.Obtain();
 | 
			
		||||
            
 | 
			
		||||
            var system = await GetGroupSystem(ctx, target, conn);
 | 
			
		||||
            var pctx = ctx.LookupContextFor(system);
 | 
			
		||||
            var memberCount = ctx.MatchPrivateFlag(pctx) ? await _repo.GetGroupMemberCount(conn, target.Id, PrivacyLevel.Public) : await _repo.GetGroupMemberCount(conn, target.Id);
 | 
			
		||||
 | 
			
		||||
            var nameField = target.Name;
 | 
			
		||||
            if (system.Name != null)
 | 
			
		||||
                nameField = $"{nameField} ({system.Name})";
 | 
			
		||||
 | 
			
		||||
            var eb = new DiscordEmbedBuilder()
 | 
			
		||||
                .WithAuthor(nameField, iconUrl: DiscordUtils.WorkaroundForUrlBug(target.IconFor(pctx)))
 | 
			
		||||
                .WithFooter($"System ID: {system.Hid} | Group ID: {target.Hid} | Created on {target.Created.FormatZoned(system)}");
 | 
			
		||||
 | 
			
		||||
            if (target.DisplayName != null)
 | 
			
		||||
                eb.AddField("Display Name", target.DisplayName);
 | 
			
		||||
 | 
			
		||||
            if (target.ListPrivacy.CanAccess(pctx))
 | 
			
		||||
            {
 | 
			
		||||
                if (memberCount == 0 && pctx == LookupContext.ByOwner)
 | 
			
		||||
                    // Only suggest the add command if this is actually the owner lol
 | 
			
		||||
                    eb.AddField("Members (0)", $"Add one with `pk;group {target.Reference()} add <member>`!", true);
 | 
			
		||||
                else
 | 
			
		||||
                    eb.AddField($"Members ({memberCount})", $"(see `pk;group {target.Reference()} list`)", true);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (target.DescriptionFor(pctx) is {} desc)
 | 
			
		||||
                eb.AddField("Description", desc);
 | 
			
		||||
 | 
			
		||||
            if (target.IconFor(pctx) is {} icon)
 | 
			
		||||
                eb.WithThumbnail(icon);
 | 
			
		||||
 | 
			
		||||
            await ctx.Reply(embed: eb.Build());
 | 
			
		||||
            await ctx.Reply(embed: await _embeds.CreateGroupEmbed(ctx, system, target));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task AddRemoveMembers(Context ctx, PKGroup target, AddRemoveOperation op)
 | 
			
		||||
 
 | 
			
		||||
@@ -61,29 +61,6 @@ namespace PluralKit.Bot
 | 
			
		||||
                await ctx.Reply($"{Emojis.Warn} You are approaching the per-system member limit ({memberCount} / {memberLimit} members). Please review your member list for unused or duplicate members.");
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public async Task MemberRandom(Context ctx)
 | 
			
		||||
        {
 | 
			
		||||
            ctx.CheckSystem();
 | 
			
		||||
 | 
			
		||||
            var randGen = new global::System.Random(); 
 | 
			
		||||
            //Maybe move this somewhere else in the file structure since it doesn't need to get created at every command
 | 
			
		||||
 | 
			
		||||
            // TODO: don't buffer these, find something else to do ig
 | 
			
		||||
            
 | 
			
		||||
            var members = await _db.Execute(c =>
 | 
			
		||||
            {
 | 
			
		||||
                if (ctx.MatchFlag("all", "a"))
 | 
			
		||||
                    return _repo.GetSystemMembers(c, ctx.System.Id);
 | 
			
		||||
                return _repo.GetSystemMembers(c, ctx.System.Id)
 | 
			
		||||
                    .Where(m => m.MemberVisibility == PrivacyLevel.Public);
 | 
			
		||||
            }).ToListAsync();
 | 
			
		||||
            
 | 
			
		||||
            if (members == null || !members.Any())
 | 
			
		||||
                throw Errors.NoMembersError;
 | 
			
		||||
            var randInt = randGen.Next(members.Count);
 | 
			
		||||
            await ctx.Reply(embed: await _embeds.CreateMemberEmbed(ctx.System, members[randInt], ctx.Guild, ctx.LookupContextFor(ctx.System)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task ViewMember(Context ctx, PKMember target)
 | 
			
		||||
        {
 | 
			
		||||
            var system = await _db.Execute(c => _repo.GetSystem(c, target.System));
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										79
									
								
								PluralKit.Bot/Commands/Random.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								PluralKit.Bot/Commands/Random.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
using PluralKit.Core;
 | 
			
		||||
 | 
			
		||||
namespace PluralKit.Bot
 | 
			
		||||
{
 | 
			
		||||
    public class Random
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IDatabase _db;
 | 
			
		||||
        private readonly ModelRepository _repo;
 | 
			
		||||
        private readonly EmbedService _embeds;
 | 
			
		||||
 | 
			
		||||
        private readonly global::System.Random randGen = new global::System.Random();
 | 
			
		||||
 | 
			
		||||
        public Random(EmbedService embeds, IDatabase db, ModelRepository repo)
 | 
			
		||||
        {
 | 
			
		||||
            _embeds = embeds;
 | 
			
		||||
            _db = db;
 | 
			
		||||
            _repo = repo;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // todo: get postgresql to return one random member/group instead of querying all members/groups
 | 
			
		||||
 | 
			
		||||
        public async Task Member(Context ctx)
 | 
			
		||||
        {
 | 
			
		||||
            ctx.CheckSystem();
 | 
			
		||||
 | 
			
		||||
            var members = await _db.Execute(c =>
 | 
			
		||||
            {
 | 
			
		||||
                if (ctx.MatchFlag("all", "a"))
 | 
			
		||||
                    return _repo.GetSystemMembers(c, ctx.System.Id);
 | 
			
		||||
                return _repo.GetSystemMembers(c, ctx.System.Id)
 | 
			
		||||
                    .Where(m => m.MemberVisibility == PrivacyLevel.Public);
 | 
			
		||||
            }).ToListAsync();
 | 
			
		||||
            
 | 
			
		||||
            if (members == null || !members.Any())
 | 
			
		||||
                throw new PKError("Your system has no members! Please create at least one member before using this command.");
 | 
			
		||||
 | 
			
		||||
            var randInt = randGen.Next(members.Count);
 | 
			
		||||
            await ctx.Reply(embed: await _embeds.CreateMemberEmbed(ctx.System, members[randInt], ctx.Guild, ctx.LookupContextFor(ctx.System)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Group(Context ctx)
 | 
			
		||||
        {
 | 
			
		||||
            ctx.CheckSystem();
 | 
			
		||||
 | 
			
		||||
            var groups = await _db.Execute(c => c.QueryGroupList(ctx.System.Id));
 | 
			
		||||
            if (!ctx.MatchFlag("all", "a"))
 | 
			
		||||
                groups = groups.Where(g => g.Visibility == PrivacyLevel.Public);
 | 
			
		||||
 | 
			
		||||
            if (groups == null || !groups.Any())
 | 
			
		||||
                throw new PKError("Your system has no groups! Please create at least one group before using this command.");
 | 
			
		||||
 | 
			
		||||
            var randInt = randGen.Next(groups.Count());
 | 
			
		||||
            await ctx.Reply(embed: await _embeds.CreateGroupEmbed(ctx, ctx.System, groups.ToArray()[randInt]));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task GroupMember(Context ctx, PKGroup group)
 | 
			
		||||
        {
 | 
			
		||||
            var opts = ctx.ParseMemberListOptions(ctx.LookupContextFor(group.System));
 | 
			
		||||
            opts.GroupFilter = group.Id;
 | 
			
		||||
 | 
			
		||||
            await using var conn = await _db.Obtain();
 | 
			
		||||
            var members = await conn.QueryMemberList(ctx.System.Id, opts.ToQueryOptions());
 | 
			
		||||
 | 
			
		||||
            if (members == null || !members.Any())
 | 
			
		||||
                throw new PKError("This group has no members! Please add at least one member to this group before using this command.");
 | 
			
		||||
 | 
			
		||||
            if (!ctx.MatchFlag("all", "a"))
 | 
			
		||||
                members = members.Where(g => g.MemberVisibility == PrivacyLevel.Public);
 | 
			
		||||
 | 
			
		||||
            var ms = members.ToList();
 | 
			
		||||
 | 
			
		||||
            var randInt = randGen.Next(ms.Count);
 | 
			
		||||
            await ctx.Reply(embed: await _embeds.CreateMemberEmbed(ctx.System, ms[randInt], ctx.Guild, ctx.LookupContextFor(ctx.System)));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user