Merge pull request #255 from dev-kittens/feat/group-random
Add random command for groups
This commit is contained in:
commit
07cd753247
@ -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 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 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 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 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 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");
|
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 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 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 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 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 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");
|
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 =
|
public static Command[] GroupCommandsTargeted =
|
||||||
{
|
{
|
||||||
GroupInfo, GroupAdd, GroupRemove, GroupMemberList, GroupRename, GroupDesc, GroupIcon, GroupPrivacy,
|
GroupInfo, GroupAdd, GroupRemove, GroupMemberList, GroupRename, GroupDesc, GroupIcon, GroupPrivacy,
|
||||||
GroupDelete
|
GroupDelete, GroupMemberRandom
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Command[] SwitchCommands = {Switch, SwitchOut, SwitchMove, SwitchDelete, SwitchDeleteAll};
|
public static Command[] SwitchCommands = {Switch, SwitchOut, SwitchMove, SwitchDelete, SwitchDeleteAll};
|
||||||
@ -196,7 +198,10 @@ namespace PluralKit.Bot
|
|||||||
if (ctx.Match("permcheck"))
|
if (ctx.Match("permcheck"))
|
||||||
return ctx.Execute<Misc>(PermCheck, m => m.PermCheckGuild(ctx));
|
return ctx.Execute<Misc>(PermCheck, m => m.PermCheckGuild(ctx));
|
||||||
if (ctx.Match("random", "r"))
|
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
|
// remove compiler warning
|
||||||
return ctx.Reply(
|
return ctx.Reply(
|
||||||
@ -382,6 +387,8 @@ namespace PluralKit.Bot
|
|||||||
await ctx.Execute<Groups>(GroupRemove, g => g.AddRemoveMembers(ctx, target, Groups.AddRemoveOperation.Remove));
|
await ctx.Execute<Groups>(GroupRemove, g => g.AddRemoveMembers(ctx, target, Groups.AddRemoveOperation.Remove));
|
||||||
else if (ctx.Match("members", "list", "ms", "l"))
|
else if (ctx.Match("members", "list", "ms", "l"))
|
||||||
await ctx.Execute<Groups>(GroupMemberList, g => g.ListGroupMembers(ctx, target));
|
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"))
|
else if (ctx.Match("privacy"))
|
||||||
await ctx.Execute<Groups>(GroupPrivacy, g => g.GroupPrivacy(ctx, target, null));
|
await ctx.Execute<Groups>(GroupPrivacy, g => g.GroupPrivacy(ctx, target, null));
|
||||||
else if (ctx.Match("public", "pub"))
|
else if (ctx.Match("public", "pub"))
|
||||||
|
@ -18,11 +18,13 @@ namespace PluralKit.Bot
|
|||||||
{
|
{
|
||||||
private readonly IDatabase _db;
|
private readonly IDatabase _db;
|
||||||
private readonly ModelRepository _repo;
|
private readonly ModelRepository _repo;
|
||||||
|
private readonly EmbedService _embeds;
|
||||||
|
|
||||||
public Groups(IDatabase db, ModelRepository repo)
|
public Groups(IDatabase db, ModelRepository repo, EmbedService embeds)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_repo = repo;
|
_repo = repo;
|
||||||
|
_embeds = embeds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task CreateGroup(Context ctx)
|
public async Task CreateGroup(Context ctx)
|
||||||
@ -280,38 +282,8 @@ namespace PluralKit.Bot
|
|||||||
public async Task ShowGroupCard(Context ctx, PKGroup target)
|
public async Task ShowGroupCard(Context ctx, PKGroup target)
|
||||||
{
|
{
|
||||||
await using var conn = await _db.Obtain();
|
await using var conn = await _db.Obtain();
|
||||||
|
|
||||||
var system = await GetGroupSystem(ctx, target, conn);
|
var system = await GetGroupSystem(ctx, target, conn);
|
||||||
var pctx = ctx.LookupContextFor(system);
|
await ctx.Reply(embed: await _embeds.CreateGroupEmbed(ctx, system, target));
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddRemoveMembers(Context ctx, PKGroup target, AddRemoveOperation op)
|
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.");
|
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)
|
public async Task ViewMember(Context ctx, PKMember target)
|
||||||
{
|
{
|
||||||
var system = await _db.Execute(c => _repo.GetSystem(c, target.System));
|
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -45,7 +45,6 @@ namespace PluralKit.Bot {
|
|||||||
public static PKError MemberNameTooLongError(int length) => new PKError($"Member name too long ({length}/{Limits.MaxMemberNameLength} characters).");
|
public static PKError MemberNameTooLongError(int length) => new PKError($"Member name too long ({length}/{Limits.MaxMemberNameLength} characters).");
|
||||||
public static PKError MemberPronounsTooLongError(int length) => new PKError($"Member pronouns too long ({length}/{Limits.MaxMemberNameLength} characters).");
|
public static PKError MemberPronounsTooLongError(int length) => new PKError($"Member pronouns too long ({length}/{Limits.MaxMemberNameLength} characters).");
|
||||||
public static PKError MemberLimitReachedError(int limit) => new PKError($"System has reached the maximum number of members ({limit}). Please delete unused members first in order to create new ones.");
|
public static PKError MemberLimitReachedError(int limit) => new PKError($"System has reached the maximum number of members ({limit}). Please delete unused members first in order to create new ones.");
|
||||||
public static PKError NoMembersError => new PKError("Your system has no members! Please create at least one member before using this command.");
|
|
||||||
|
|
||||||
public static PKError InvalidColorError(string color) => new PKError($"\"{color}\" is not a valid color. Color must be in 6-digit RGB hex format (eg. #ff0000).");
|
public static PKError InvalidColorError(string color) => new PKError($"\"{color}\" is not a valid color. Color must be in 6-digit RGB hex format (eg. #ff0000).");
|
||||||
public static PKError BirthdayParseError(string birthday) => new PKError($"\"{birthday}\" could not be parsed as a valid date. Try a format like \"2016-12-24\" or \"May 3 1996\".");
|
public static PKError BirthdayParseError(string birthday) => new PKError($"\"{birthday}\" could not be parsed as a valid date. Try a format like \"2016-12-24\" or \"May 3 1996\".");
|
||||||
|
@ -43,6 +43,7 @@ namespace PluralKit.Bot
|
|||||||
builder.RegisterType<MemberGroup>().AsSelf();
|
builder.RegisterType<MemberGroup>().AsSelf();
|
||||||
builder.RegisterType<MemberProxy>().AsSelf();
|
builder.RegisterType<MemberProxy>().AsSelf();
|
||||||
builder.RegisterType<Misc>().AsSelf();
|
builder.RegisterType<Misc>().AsSelf();
|
||||||
|
builder.RegisterType<Random>().AsSelf();
|
||||||
builder.RegisterType<ServerConfig>().AsSelf();
|
builder.RegisterType<ServerConfig>().AsSelf();
|
||||||
builder.RegisterType<Switch>().AsSelf();
|
builder.RegisterType<Switch>().AsSelf();
|
||||||
builder.RegisterType<System>().AsSelf();
|
builder.RegisterType<System>().AsSelf();
|
||||||
|
@ -157,6 +157,42 @@ namespace PluralKit.Bot {
|
|||||||
return eb.Build();
|
return eb.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<DiscordEmbed> CreateGroupEmbed(Context ctx, PKSystem system, PKGroup target)
|
||||||
|
{
|
||||||
|
await using var conn = await _db.Obtain();
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return eb.Build();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<DiscordEmbed> CreateFronterEmbed(PKSwitch sw, DateTimeZone zone, LookupContext ctx)
|
public async Task<DiscordEmbed> CreateFronterEmbed(PKSwitch sw, DateTimeZone zone, LookupContext ctx)
|
||||||
{
|
{
|
||||||
var members = await _db.Execute(c => _repo.GetSwitchMembers(c, sw.Id).ToListAsync().AsTask());
|
var members = await _db.Execute(c => _repo.GetSwitchMembers(c, sw.Id).ToListAsync().AsTask());
|
||||||
|
@ -54,7 +54,6 @@ Words in **\<angle brackets>** or **[square brackets]** mean fill-in-the-blank.
|
|||||||
- `pk;member <name> color [color]` - Changes the color of a member.
|
- `pk;member <name> color [color]` - Changes the color of a member.
|
||||||
- `pk;member <name> birthdate [birthdate]` - Changes the birthday of a member.
|
- `pk;member <name> birthdate [birthdate]` - Changes the birthday of a member.
|
||||||
- `pk;member <name> delete` - Deletes a member.
|
- `pk;member <name> delete` - Deletes a member.
|
||||||
- `pk;random` - Shows the member card of a randomly selected member in your system.
|
|
||||||
|
|
||||||
## Group commands
|
## Group commands
|
||||||
*Replace `<name>` with a group's name, 5-character ID or display name. For most commands, adding `-clear` will clear/delete the field.*
|
*Replace `<name>` with a group's name, 5-character ID or display name. For most commands, adding `-clear` will clear/delete the field.*
|
||||||
@ -62,6 +61,7 @@ Words in **\<angle brackets>** or **[square brackets]** mean fill-in-the-blank.
|
|||||||
- `pk;group new <name>` - Creates a new group.
|
- `pk;group new <name>` - Creates a new group.
|
||||||
- `pk;group list` - Lists all groups in your system.
|
- `pk;group list` - Lists all groups in your system.
|
||||||
- `pk;group <group> list` - Lists all members in a group.
|
- `pk;group <group> list` - Lists all members in a group.
|
||||||
|
- `pk;group <group> random` - Shows the info card of a randomly selected member in a group.
|
||||||
- `pk;group <group> rename <new name>` - Renames a group.
|
- `pk;group <group> rename <new name>` - Renames a group.
|
||||||
- `pk;group <group> displayname [display name]` - Shows or changes a group's display name.
|
- `pk;group <group> displayname [display name]` - Shows or changes a group's display name.
|
||||||
- `pk;group <group> description [description]` - Shows or changes a group's description.
|
- `pk;group <group> description [description]` - Shows or changes a group's description.
|
||||||
@ -89,6 +89,7 @@ Words in **\<angle brackets>** or **[square brackets]** mean fill-in-the-blank.
|
|||||||
- `pk;blacklist remove <#channel> [#channel...]` - Removes the given channel(s) from the proxy blacklist.
|
- `pk;blacklist remove <#channel> [#channel...]` - Removes the given channel(s) from the proxy blacklist.
|
||||||
|
|
||||||
## Utility
|
## Utility
|
||||||
|
- `pk;random [-group]` - Shows the info card of a randomly selected member [or group] in your system.
|
||||||
- `pk;message <message id / message link>` - Looks up information about a proxied message by its message ID or link.
|
- `pk;message <message id / message link>` - Looks up information about a proxied message by its message ID or link.
|
||||||
- `pk;invite` - Sends the bot invite link for PluralKit.
|
- `pk;invite` - Sends the bot invite link for PluralKit.
|
||||||
- `pk;import` - Imports a data file from PluralKit or Tupperbox.
|
- `pk;import` - Imports a data file from PluralKit or Tupperbox.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user