mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-04 04:56:49 +00:00
feat: add text-to-speech option to members (#570)
Merges PluralKit/PluralKit#570
This commit is contained in:
parent
68cd21fb2f
commit
e58b3c7274
16 changed files with 90 additions and 6 deletions
|
|
@ -11,5 +11,6 @@ public record ExecuteWebhookRequest
|
|||
public Sticker[] Stickers { get; init; }
|
||||
public Message.Attachment[] Attachments { get; set; }
|
||||
public AllowedMentions? AllowedMentions { get; init; }
|
||||
public bool? Tts { get; init; }
|
||||
public Message.MessageFlags? Flags { get; set; }
|
||||
}
|
||||
|
|
@ -54,6 +54,7 @@ public partial class CommandTree
|
|||
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 MemberAutoproxy = new Command("member autoproxy", "member <member> autoproxy [on|off]", "Sets whether a member will be autoproxied when autoproxy is set to latch or front mode.");
|
||||
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 MemberTts = new Command("member text-to-speech", "member <member> text-to-speech [on|off]", "Sets whether to send a member's messages as text-to-speech messages.");
|
||||
public static Command MemberRandom = new Command("system random", "system [system] random", "Shows the info card of a randomly selected member in a system.");
|
||||
public static Command MemberId = new Command("member id", "member [member] id", "Prints a member's id.");
|
||||
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");
|
||||
|
|
@ -116,7 +117,7 @@ public partial class CommandTree
|
|||
public static Command[] MemberCommands =
|
||||
{
|
||||
MemberInfo, MemberNew, MemberRename, MemberDisplayName, MemberServerName, MemberDesc, MemberPronouns,
|
||||
MemberColor, MemberBirthday, MemberProxy, MemberAutoproxy, MemberKeepProxy, MemberGroups, MemberGroupAdd,
|
||||
MemberColor, MemberBirthday, MemberProxy, MemberAutoproxy, MemberKeepProxy, MemberTts, MemberGroups, MemberGroupAdd,
|
||||
MemberGroupRemove, MemberDelete, MemberAvatar, MemberServerAvatar, MemberBannerImage, MemberPrivacy,
|
||||
MemberRandom
|
||||
};
|
||||
|
|
|
|||
|
|
@ -336,6 +336,8 @@ public partial class CommandTree
|
|||
await ctx.Execute<MemberEdit>(MemberAutoproxy, m => m.MemberAutoproxy(ctx, target));
|
||||
else if (ctx.Match("keepproxy", "keeptags", "showtags", "kp"))
|
||||
await ctx.Execute<MemberEdit>(MemberKeepProxy, m => m.KeepProxy(ctx, target));
|
||||
else if (ctx.Match("texttospeech", "text-to-speech", "tts"))
|
||||
await ctx.Execute<MemberEdit>(MemberTts, m => m.Tts(ctx, target));
|
||||
else if (ctx.Match("id"))
|
||||
await ctx.Execute<Member>(MemberId, m => m.DisplayId(ctx, target));
|
||||
else if (ctx.Match("privacy"))
|
||||
|
|
|
|||
|
|
@ -532,6 +532,47 @@ public class MemberEdit
|
|||
$"{Emojis.Success} Member proxy tags will now not be included in the resulting message when proxying.");
|
||||
}
|
||||
|
||||
public async Task Tts(Context ctx, PKMember target)
|
||||
{
|
||||
ctx.CheckSystem().CheckOwnMember(target);
|
||||
|
||||
bool newValue;
|
||||
if (ctx.Match("on", "enabled", "true", "yes"))
|
||||
{
|
||||
newValue = true;
|
||||
}
|
||||
else if (ctx.Match("off", "disabled", "false", "no"))
|
||||
{
|
||||
newValue = false;
|
||||
}
|
||||
else if (ctx.HasNext())
|
||||
{
|
||||
throw new PKSyntaxError("You must pass either \"on\" or \"off\".");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (target.Tts)
|
||||
await ctx.Reply(
|
||||
"This member has text-to-speech **enabled**, which means their messages **will be** sent as text-to-speech messages.");
|
||||
else
|
||||
await ctx.Reply(
|
||||
"This member has text-to-speech **disabled**, which means their messages **will not** be sent as text-to-speech messages.");
|
||||
return;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
var patch = new MemberPatch { Tts = Partial<bool>.Present(newValue) };
|
||||
await ctx.Repository.UpdateMember(target.Id, patch);
|
||||
|
||||
if (newValue)
|
||||
await ctx.Reply(
|
||||
$"{Emojis.Success} Member's messages will now be sent as text-to-speech messages.");
|
||||
else
|
||||
await ctx.Reply(
|
||||
$"{Emojis.Success} Member messages will no longer be sent as text-to-speech messages.");
|
||||
}
|
||||
|
||||
public async Task MemberAutoproxy(Context ctx, PKMember target)
|
||||
{
|
||||
if (ctx.System == null) throw Errors.NoSystemError;
|
||||
|
|
|
|||
|
|
@ -230,6 +230,11 @@ public class ProxyService
|
|||
var rootChannel = await _cache.GetRootChannel(trigger.ChannelId);
|
||||
var threadId = messageChannel.IsThread() ? messageChannel.Id : (ulong?)null;
|
||||
var guild = await _cache.GetGuild(trigger.GuildId.Value);
|
||||
var guildMember = await _rest.GetGuildMember(trigger.GuildId!.Value, trigger.Author.Id);
|
||||
|
||||
//If the member is a text-to-speech member and the user can send text-to-speech messages in that channel, turn text-to-speech on
|
||||
var senderPermissions = PermissionExtensions.PermissionsFor(guild, messageChannel, trigger.Author.Id, guildMember);
|
||||
var tts = match.Member.Tts && senderPermissions.HasFlag(PermissionSet.SendTtsMessages);
|
||||
|
||||
var proxyMessage = await _webhookExecutor.ExecuteWebhook(new ProxyRequest
|
||||
{
|
||||
|
|
@ -245,6 +250,7 @@ public class ProxyService
|
|||
Stickers = trigger.StickerItems,
|
||||
AllowEveryone = allowEveryone,
|
||||
Flags = trigger.Flags.HasFlag(Message.MessageFlags.VoiceMessage) ? Message.MessageFlags.VoiceMessage : null,
|
||||
Tts = tts,
|
||||
});
|
||||
await HandleProxyExecutedActions(ctx, autoproxySettings, trigger, proxyMessage, match);
|
||||
}
|
||||
|
|
@ -291,6 +297,9 @@ public class ProxyService
|
|||
if (!senderPermissions.HasFlag(PermissionSet.SendMessages))
|
||||
throw new PKError("You don't have permission to send messages in the channel that message is in.");
|
||||
|
||||
//If the member is a text-to-speech member and the user can send text-to-speech messages in that channel, turn text-to-speech on
|
||||
var tts = member.Tts && senderPermissions.HasFlag(PermissionSet.SendTtsMessages);
|
||||
|
||||
// Mangle embeds (for reply embed color changing)
|
||||
var mangledEmbeds = originalMsg.Embeds!.Select(embed => MangleReproxyEmbed(embed, member)).Where(embed => embed != null).ToArray();
|
||||
|
||||
|
|
@ -309,6 +318,7 @@ public class ProxyService
|
|||
Stickers = originalMsg.StickerItems!,
|
||||
AllowEveryone = allowEveryone,
|
||||
Flags = originalMsg.Flags.HasFlag(Message.MessageFlags.VoiceMessage) ? Message.MessageFlags.VoiceMessage : null,
|
||||
Tts = tts,
|
||||
});
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ public record ProxyRequest
|
|||
public Sticker[] Stickers { get; init; }
|
||||
public bool AllowEveryone { get; init; }
|
||||
public Message.MessageFlags? Flags { get; init; }
|
||||
public bool Tts { get; init; }
|
||||
}
|
||||
|
||||
public class WebhookExecutorService
|
||||
|
|
@ -131,6 +132,7 @@ public class WebhookExecutorService
|
|||
Embeds = req.Embeds,
|
||||
Stickers = req.Stickers,
|
||||
Flags = req.Flags,
|
||||
Tts = req.Tts,
|
||||
};
|
||||
|
||||
MultipartFile[] files = null;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ public class ProxyMember
|
|||
public MemberId Id { get; }
|
||||
public IReadOnlyCollection<ProxyTag> ProxyTags { get; } = new ProxyTag[0];
|
||||
public bool KeepProxy { get; }
|
||||
public bool Tts { get; }
|
||||
|
||||
public string? ServerName { get; }
|
||||
public string? DisplayName { get; }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
create function message_context(account_id bigint, guild_id bigint, channel_id bigint, thread_id bigint)
|
||||
create function message_context(account_id bigint, guild_id bigint, channel_id bigint, thread_id bigint)
|
||||
returns table (
|
||||
system_id int,
|
||||
log_channel bigint,
|
||||
|
|
@ -68,6 +68,7 @@ create function proxy_members(account_id bigint, guild_id bigint)
|
|||
id int,
|
||||
proxy_tags proxy_tag[],
|
||||
keep_proxy bool,
|
||||
tts bool,
|
||||
|
||||
server_name text,
|
||||
display_name text,
|
||||
|
|
@ -87,6 +88,7 @@ as $$
|
|||
members.id as id,
|
||||
members.proxy_tags as proxy_tags,
|
||||
members.keep_proxy as keep_proxy,
|
||||
members.tts as tts,
|
||||
|
||||
-- Name info
|
||||
member_guild.display_name as server_name,
|
||||
|
|
|
|||
6
PluralKit.Core/Database/Migrations/38.sql
Normal file
6
PluralKit.Core/Database/Migrations/38.sql
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
-- database version 38
|
||||
-- add proxy tag privacy
|
||||
|
||||
alter table members add column tts boolean not null default false;
|
||||
|
||||
update info set schema_version = 38;
|
||||
|
|
@ -9,7 +9,7 @@ namespace PluralKit.Core;
|
|||
internal class DatabaseMigrator
|
||||
{
|
||||
private const string RootPath = "PluralKit.Core.Database"; // "resource path" root for SQL files
|
||||
private const int TargetSchemaVersion = 37;
|
||||
private const int TargetSchemaVersion = 38;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public DatabaseMigrator(ILogger logger)
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ public class PKMember
|
|||
public string Description { get; private set; }
|
||||
public ICollection<ProxyTag> ProxyTags { get; private set; }
|
||||
public bool KeepProxy { get; private set; }
|
||||
public bool Tts { get; private set; }
|
||||
public Instant Created { get; private set; }
|
||||
public int MessageCount { get; private set; }
|
||||
public Instant? LastMessageTimestamp { get; private set; }
|
||||
|
|
@ -137,6 +138,7 @@ public static class PKMemberExt
|
|||
o.Add("description", member.DescriptionFor(ctx));
|
||||
o.Add("created", member.CreatedFor(ctx)?.FormatExport());
|
||||
o.Add("keep_proxy", member.KeepProxy);
|
||||
o.Add("tts", member.Tts);
|
||||
|
||||
o.Add("autoproxy_enabled", ctx == LookupContext.ByOwner ? member.AllowAutoproxy : null);
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ public class MemberPatch: PatchObject
|
|||
public Partial<string?> Description { get; set; }
|
||||
public Partial<ProxyTag[]> ProxyTags { get; set; }
|
||||
public Partial<bool> KeepProxy { get; set; }
|
||||
public Partial<bool> Tts { get; set; }
|
||||
public Partial<int> MessageCount { get; set; }
|
||||
public Partial<bool> AllowAutoproxy { get; set; }
|
||||
public Partial<PrivacyLevel> Visibility { get; set; }
|
||||
|
|
@ -46,6 +47,7 @@ public class MemberPatch: PatchObject
|
|||
.With("description", Description)
|
||||
.With("proxy_tags", ProxyTags)
|
||||
.With("keep_proxy", KeepProxy)
|
||||
.With("tts", Tts)
|
||||
.With("message_count", MessageCount)
|
||||
.With("allow_autoproxy", AllowAutoproxy)
|
||||
.With("member_visibility", Visibility)
|
||||
|
|
@ -126,6 +128,7 @@ public class MemberPatch: PatchObject
|
|||
if (o.ContainsKey("pronouns")) patch.Pronouns = o.Value<string>("pronouns").NullIfEmpty();
|
||||
if (o.ContainsKey("description")) patch.Description = o.Value<string>("description").NullIfEmpty();
|
||||
if (o.ContainsKey("keep_proxy")) patch.KeepProxy = o.Value<bool>("keep_proxy");
|
||||
if (o.ContainsKey("tts")) patch.Tts = o.Value<bool>("tts");
|
||||
|
||||
if (isImport)
|
||||
{
|
||||
|
|
@ -223,6 +226,9 @@ public class MemberPatch: PatchObject
|
|||
if (KeepProxy.IsPresent)
|
||||
o.Add("keep_proxy", KeepProxy.Value);
|
||||
|
||||
if (Tts.IsPresent)
|
||||
o.Add("tts", Tts.Value);
|
||||
|
||||
if (
|
||||
Visibility.IsPresent
|
||||
|| NamePrivacy.IsPresent
|
||||
|
|
|
|||
|
|
@ -61,10 +61,11 @@ export interface Member {
|
|||
banner?: string;
|
||||
description?: string;
|
||||
created?: string;
|
||||
keep_proxy?: boolean
|
||||
keep_proxy?: boolean;
|
||||
tts?: boolean;
|
||||
system?: string;
|
||||
proxy_tags?: Array<proxytag>;
|
||||
privacy?: MemberPrivacy
|
||||
privacy?: MemberPrivacy;
|
||||
}
|
||||
|
||||
export interface GroupPrivacy {
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ Every PluralKit entity has two IDs: a short (5-character) ID and a longer UUID.
|
|||
|created|?datetime||
|
||||
|proxy_tags|array of [ProxyTag objects](#proxytag-object)|
|
||||
|keep_proxy|boolean||
|
||||
|tts|boolean||
|
||||
|autoproxy_enabled|?boolean||
|
||||
|message_count|?int||
|
||||
|last_message_timestamp|?datetime||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ You can have a space after `pk;`, e.g. `pk;system` and `pk; system` will do the
|
|||
- `pk;member <member> proxy remove [tags]` - Removes a proxy tag from a member.
|
||||
- `pk;member <member> autoproxy [on|off]` - Sets whether a member will be autoproxied when autoproxy is set to latch or front mode.
|
||||
- `pk;member <member> keepproxy [on|off]` - Sets whether to include a member's proxy tags in the proxied message.
|
||||
- `pk;member <member> tts [on|off]` - Sets whether to send a member's messages as text-to-speech messages.
|
||||
- `pk;member <member> pronouns [pronouns]` - Changes the pronouns of a member.
|
||||
- `pk;member <member> color [color]` - Changes the color of a member.
|
||||
- `pk;member <member> birthdate [birthdate|today]` - Changes the birthday of a member.
|
||||
|
|
|
|||
|
|
@ -358,6 +358,13 @@ The practical effect of this is:
|
|||
* **Keep proxy tags on:** `[Message goes here]` typed -> `[Message goes here]` displayed
|
||||
* **Keep proxy tags off:** `[Message goes here]` typed -> `Message goes here` displayed
|
||||
|
||||
### Sending text-to-speech messages
|
||||
If you'd like your proxied messages to be sent as text-to-speech messages (read off out loud to anyone who has the channel focused) you can enable the text-to-speech option for a given member, like so:
|
||||
|
||||
pk;member John text-to-speech on
|
||||
|
||||
Turning the option off is similar - replace "on" with "off" in the command. The default value for every member is off. If you are not allowed to send text-to-speech messages in a server, this feature will not work.
|
||||
|
||||
### Disabling proxying on a per-server basis
|
||||
If you need to disable or re-enable proxying messages for your system entirely in a specific server (for example, if you'd like to
|
||||
use a different proxy bot there), you can use the commands:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue