Barebones, untested sort/filtering
This commit is contained in:
		
							
								
								
									
										12
									
								
								PluralKit.Bot/Lists/IListRenderer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								PluralKit.Bot/Lists/IListRenderer.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
using DSharpPlus.Entities;
 | 
			
		||||
 | 
			
		||||
namespace PluralKit.Bot
 | 
			
		||||
{
 | 
			
		||||
    public interface IListRenderer
 | 
			
		||||
    {
 | 
			
		||||
        int MembersPerPage { get; }
 | 
			
		||||
        void RenderPage(DiscordEmbedBuilder eb, IEnumerable<PKListMember> members);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										62
									
								
								PluralKit.Bot/Lists/LongRenderer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								PluralKit.Bot/Lists/LongRenderer.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
using DSharpPlus.Entities;
 | 
			
		||||
 | 
			
		||||
using Humanizer;
 | 
			
		||||
 | 
			
		||||
using PluralKit.Core;
 | 
			
		||||
 | 
			
		||||
namespace PluralKit.Bot
 | 
			
		||||
{
 | 
			
		||||
    public class LongRenderer: IListRenderer
 | 
			
		||||
    {
 | 
			
		||||
        public int MembersPerPage => 5;
 | 
			
		||||
 | 
			
		||||
        private readonly MemberFields _fields;
 | 
			
		||||
        public LongRenderer(MemberFields fields)
 | 
			
		||||
        {
 | 
			
		||||
            _fields = fields;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RenderPage(DiscordEmbedBuilder eb, IEnumerable<PKListMember> members)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var m in members)
 | 
			
		||||
            {
 | 
			
		||||
                var profile = $"**ID**: {m.Hid}";
 | 
			
		||||
                if (_fields.ShowDisplayName && m.DisplayName != null) profile += $"\n**Display name**: {m.DisplayName}";
 | 
			
		||||
                if (_fields.ShowPronouns && m.Pronouns != null) profile += $"\n**Pronouns**: {m.Pronouns}";
 | 
			
		||||
                if (_fields.ShowBirthday && m.Birthday != null) profile += $"\n**Birthdate**: {m.BirthdayString}";
 | 
			
		||||
                if (_fields.ShowPronouns && m.ProxyTags.Count > 0) profile += $"\n**Proxy tags:** {m.ProxyTagsString()}";
 | 
			
		||||
                if (_fields.ShowMessageCount && m.MessageCount > 0) profile += $"\n**Message count:** {m.MessageCount}";
 | 
			
		||||
                if (_fields.ShowDescription && m.Description != null) profile += $"\n\n{m.Description}";
 | 
			
		||||
                if (_fields.ShowPrivacy && m.MemberPrivacy == PrivacyLevel.Private)
 | 
			
		||||
                    profile += "\n*(this member is private)*";
 | 
			
		||||
 | 
			
		||||
                eb.AddField(m.Name, profile.Truncate(1024));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public class MemberFields
 | 
			
		||||
        {
 | 
			
		||||
            public bool ShowDisplayName = true;
 | 
			
		||||
            public bool ShowCreated = true;
 | 
			
		||||
            public bool ShowMessageCount = true;
 | 
			
		||||
            public bool ShowPronouns = true;
 | 
			
		||||
            public bool ShowBirthday = true;
 | 
			
		||||
            public bool ShowProxyTags = true;
 | 
			
		||||
            public bool ShowDescription = true;
 | 
			
		||||
            public bool ShowPrivacy = true;
 | 
			
		||||
            
 | 
			
		||||
            public static MemberFields FromFlags(Context ctx)
 | 
			
		||||
            {
 | 
			
		||||
                // TODO
 | 
			
		||||
                return new MemberFields
 | 
			
		||||
                {
 | 
			
		||||
                    ShowMessageCount = false,
 | 
			
		||||
                    ShowCreated = false
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								PluralKit.Bot/Lists/PKListMember.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								PluralKit.Bot/Lists/PKListMember.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
using PluralKit.Core;
 | 
			
		||||
 | 
			
		||||
namespace PluralKit.Bot
 | 
			
		||||
{
 | 
			
		||||
    public class PKListMember: PKMember
 | 
			
		||||
    {
 | 
			
		||||
        public int MessageCount { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								PluralKit.Bot/Lists/ShortRenderer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								PluralKit.Bot/Lists/ShortRenderer.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
 | 
			
		||||
using DSharpPlus.Entities;
 | 
			
		||||
 | 
			
		||||
namespace PluralKit.Bot
 | 
			
		||||
{
 | 
			
		||||
    public class ShortRenderer: IListRenderer
 | 
			
		||||
    {
 | 
			
		||||
        public int MembersPerPage => 25;
 | 
			
		||||
        
 | 
			
		||||
        public void RenderPage(DiscordEmbedBuilder eb, IEnumerable<PKListMember> members)
 | 
			
		||||
        {
 | 
			
		||||
            eb.Description = string.Join("\n", members.Select(m =>
 | 
			
		||||
            {
 | 
			
		||||
                if (m.HasProxyTags)
 | 
			
		||||
                {
 | 
			
		||||
                    var proxyTagsString = m.ProxyTagsString().SanitizeMentions();
 | 
			
		||||
                    if (proxyTagsString.Length > 100) // arbitrary threshold for now, tweak?
 | 
			
		||||
                        proxyTagsString = "tags too long, see member card";
 | 
			
		||||
 | 
			
		||||
                    return $"[`{m.Hid}`] **{m.Name.SanitizeMentions()}** *({proxyTagsString})*";
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return $"[`{m.Hid}`] **{m.Name.SanitizeMentions()}**";
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										154
									
								
								PluralKit.Bot/Lists/SortFilterOptions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								PluralKit.Bot/Lists/SortFilterOptions.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,154 @@
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using PluralKit.Core;
 | 
			
		||||
 | 
			
		||||
namespace PluralKit.Bot
 | 
			
		||||
{
 | 
			
		||||
    public class SortFilterOptions
 | 
			
		||||
    {
 | 
			
		||||
        public SortProperty SortProperty = SortProperty.Name;
 | 
			
		||||
        public SortDirection Direction = SortDirection.Ascending;
 | 
			
		||||
        public PrivacyFilter PrivacyFilter = PrivacyFilter.PublicOnly;
 | 
			
		||||
        public string Filter = null;
 | 
			
		||||
        public bool SearchInDescription = false;
 | 
			
		||||
 | 
			
		||||
        public string CreateFilterString()
 | 
			
		||||
        {
 | 
			
		||||
            // TODO
 | 
			
		||||
            return "uwu";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string BuildQuery()
 | 
			
		||||
        {
 | 
			
		||||
            // Select clause
 | 
			
		||||
            StringBuilder query = new StringBuilder();
 | 
			
		||||
            query.Append(SortProperty switch
 | 
			
		||||
            {
 | 
			
		||||
                SortProperty.MessageCount =>
 | 
			
		||||
                "select members.*, count(messages.*) as message_count, max(messages.mid) as last_message from members",
 | 
			
		||||
                SortProperty.LastMessage =>
 | 
			
		||||
                "select members.*, count(messages.*) as message_count, max(messages.mid) as last_message from members",
 | 
			
		||||
                SortProperty.LastSwitch => "select members.*, max(switches.timestamp) as last_switch_time from members",
 | 
			
		||||
                _ => "select members.* from members"
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Join clauses
 | 
			
		||||
            query.Append(SortProperty switch
 | 
			
		||||
            {
 | 
			
		||||
                SortProperty.MessageCount => " left join messages on messages.member = members.id",
 | 
			
		||||
                SortProperty.LastMessage => " left join messages on messages.member = members.id",
 | 
			
		||||
                SortProperty.LastSwitch =>
 | 
			
		||||
                " left join switch_members on switch_members.member = members.id left join switches on switch_members.switch = switches.id",
 | 
			
		||||
                _ => ""
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Where clauses
 | 
			
		||||
            query.Append(" where members.system = @System");
 | 
			
		||||
 | 
			
		||||
            // Privacy filter
 | 
			
		||||
            query.Append(PrivacyFilter switch
 | 
			
		||||
            {
 | 
			
		||||
                PrivacyFilter.PrivateOnly => $" and members.member_privacy = {(int) PrivacyLevel.Private}",
 | 
			
		||||
                PrivacyFilter.PublicOnly => $" and members.member_privacy = {(int) PrivacyLevel.Public}",
 | 
			
		||||
                _ => ""
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // String filter
 | 
			
		||||
            if (Filter != null)
 | 
			
		||||
            {
 | 
			
		||||
                // Use position rather than ilike to not bother with escaping and such
 | 
			
		||||
                query.Append(" and (");
 | 
			
		||||
                query.Append(
 | 
			
		||||
                    "position(lower(@Filter) in lower(members.name)) > 0 or position(lower(@Filter) in lower(coalesce(members.display_name, ''))) > 0");
 | 
			
		||||
                if (SearchInDescription)
 | 
			
		||||
                    query.Append(" or position(lower(@Filter) in lower(coalesce(members.description, ''))) > 0");
 | 
			
		||||
                query.Append(")");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Group clause
 | 
			
		||||
            query.Append(SortProperty switch
 | 
			
		||||
            {
 | 
			
		||||
                SortProperty.MessageCount => " group by members.id",
 | 
			
		||||
                SortProperty.LastMessage => " group by members.id",
 | 
			
		||||
                SortProperty.LastSwitch => " group by members.id",
 | 
			
		||||
                _ => ""
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Order clause
 | 
			
		||||
            query.Append(SortProperty switch
 | 
			
		||||
            {
 | 
			
		||||
                SortProperty.Hid => " order by members.hid",
 | 
			
		||||
                SortProperty.CreationDate => " order by members.created",
 | 
			
		||||
                SortProperty.Birthdate =>
 | 
			
		||||
                " order by extract(month from members.birthday), extract(day from members.birthday)",
 | 
			
		||||
                SortProperty.MessageCount => " order by count(messages.mid)",
 | 
			
		||||
                SortProperty.LastMessage => " order by max(messages.mid)",
 | 
			
		||||
                SortProperty.LastSwitch => " order by max(switches.timestamp)",
 | 
			
		||||
                _ => " order by members.name"
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Order direction
 | 
			
		||||
            if (Direction == SortDirection.Descending)
 | 
			
		||||
                query.Append(" desc");
 | 
			
		||||
 | 
			
		||||
            return query.ToString();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static SortFilterOptions FromFlags(Context ctx)
 | 
			
		||||
        {
 | 
			
		||||
            var p = new SortFilterOptions();
 | 
			
		||||
            
 | 
			
		||||
            // Direction
 | 
			
		||||
            if (ctx.MatchFlag("r", "rev", "reverse", "desc", "descending"))
 | 
			
		||||
                p.Direction = SortDirection.Descending;
 | 
			
		||||
            
 | 
			
		||||
            // Sort
 | 
			
		||||
            if (ctx.MatchFlag("by-id", "bi"))
 | 
			
		||||
                p.SortProperty = SortProperty.Hid;
 | 
			
		||||
            else if (ctx.MatchFlag("by-msgcount", "by-mc", "by-msgs", "bm"))
 | 
			
		||||
                p.SortProperty = SortProperty.MessageCount;
 | 
			
		||||
            else if (ctx.MatchFlag("by-date", "by-time", "by-created", "bc"))
 | 
			
		||||
                p.SortProperty = SortProperty.CreationDate;
 | 
			
		||||
            else if (ctx.MatchFlag("by-switch"))
 | 
			
		||||
                p.SortProperty = SortProperty.LastSwitch;
 | 
			
		||||
            else if (ctx.MatchFlag("by-last-message"))
 | 
			
		||||
                p.SortProperty = SortProperty.LastMessage;
 | 
			
		||||
            
 | 
			
		||||
            // Description
 | 
			
		||||
            if (ctx.MatchFlag("desc"))
 | 
			
		||||
                p.SearchInDescription = true;
 | 
			
		||||
            
 | 
			
		||||
            // Privacy
 | 
			
		||||
            if (ctx.MatchFlag("a", "all"))
 | 
			
		||||
                p.PrivacyFilter = PrivacyFilter.All;
 | 
			
		||||
            else if (ctx.MatchFlag("po", "private", "private-only", "only-private", "priv"))
 | 
			
		||||
                p.PrivacyFilter = PrivacyFilter.PrivateOnly;
 | 
			
		||||
            
 | 
			
		||||
            return p;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public enum SortProperty
 | 
			
		||||
    {
 | 
			
		||||
        Name,
 | 
			
		||||
        Hid,
 | 
			
		||||
        MessageCount,
 | 
			
		||||
        CreationDate,
 | 
			
		||||
        LastSwitch,
 | 
			
		||||
        LastMessage,
 | 
			
		||||
        Birthdate
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public enum SortDirection
 | 
			
		||||
    {
 | 
			
		||||
        Ascending,
 | 
			
		||||
        Descending
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public enum PrivacyFilter
 | 
			
		||||
    {
 | 
			
		||||
        All,
 | 
			
		||||
        PublicOnly,
 | 
			
		||||
        PrivateOnly
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user