feat: add delete account and invite permissions to plugin

This commit is contained in:
Anna 2022-07-19 18:42:44 -04:00
parent 9a3ba3f0a5
commit 89012bd072
13 changed files with 140 additions and 8 deletions

View File

@ -289,6 +289,27 @@ internal class Client : IDisposable {
}
}
internal async Task<string?> DeleteAccount() {
var response = await this.QueueMessageAndWait(new RequestKind.DeleteAccount(new DeleteAccountRequest()));
return response switch {
ResponseKind.Error { Response.Error: var error } => error,
ResponseKind.DeleteAccount => null,
_ => throw new Exception("Unexpected response"),
};
}
internal async Task DeleteAccountToast() {
var message = await this.DeleteAccount();
if (message != null) {
this.Plugin.ShowError($"Could not delete account: {message}");
return;
}
this.Plugin.Config.Configs.Remove(this.Plugin.ClientState.LocalContentId);
this.Plugin.SaveConfig();
this.StopLoop();
}
/// <summary>
/// Attempts to register the user after the challenge has been completed.
/// </summary>
@ -337,6 +358,7 @@ internal class Client : IDisposable {
var response = await this.QueueMessageAndWait(new RequestKind.Authenticate(new AuthenticateRequest {
Key = key,
PublicKey = this.KeyPair.GetPublicKey(),
AllowInvites = true,
}));
var success = response switch {
@ -488,6 +510,21 @@ internal class Client : IDisposable {
}));
}
internal async Task<bool> AllowInvites(bool allow) {
var resp = await this.QueueMessageAndWait(new RequestKind.AllowInvites(new AllowInvitesRequest {
Allowed = allow,
}));
return resp is ResponseKind.AllowInvites { Response.Allowed: var respAllowed } && respAllowed == allow;
}
internal async Task AllowInvitesToast(bool allow) {
if (!await this.AllowInvites(allow)) {
this.Plugin.ShowError("Could not set invite permissions.");
}
}
private bool _up;
#pragma warning disable CS4014
@ -503,6 +540,10 @@ internal class Client : IDisposable {
return;
}
this.Channels.Clear();
this.InvitedChannels.Clear();
this.ChannelRanks.Clear();
this.Waiters.Clear();
this.ToSend = System.Threading.Channels.Channel.CreateUnbounded<(RequestContainer, ChannelWriter<ChannelReader<ResponseKind>>?)>();
await this._waitersSemaphore.WaitAsync();
try {

View File

@ -42,6 +42,7 @@ internal class ConfigInfo {
public Dictionary<Guid, string> ChannelMarkers = new();
public Dictionary<Guid, XivChatType> ChannelChannels = new();
public int TutorialStep;
public bool AllowInvites = true;
internal string GetName(Guid id) => this.Channels.TryGetValue(id, out var channel)
? channel.Name

View File

@ -53,16 +53,16 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="ASodium" Version="0.5.3"/>
<PackageReference Include="Dalamud.ContextMenu" Version="1.1.1"/>
<PackageReference Include="DalamudPackager" Version="2.1.7"/>
<PackageReference Include="MessagePack" Version="2.4.35"/>
<PackageReference Include="System.Net.WebSockets.Client" Version="4.3.2"/>
<PackageReference Include="System.Threading.Channels" Version="6.0.0"/>
<PackageReference Include="ASodium" Version="0.5.3" />
<PackageReference Include="Dalamud.ContextMenu" Version="1.1.1" />
<PackageReference Include="DalamudPackager" Version="2.1.7" />
<PackageReference Include="MessagePack" Version="2.4.35" />
<PackageReference Include="System.Net.WebSockets.Client" Version="4.3.2" />
<PackageReference Include="System.Threading.Channels" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<Content Include="..\icon.png" Link="images/icon.png" CopyToOutputDirectory="PreserveNewest" Visible="false"/>
<Content Include="..\icon.png" Link="images/icon.png" CopyToOutputDirectory="PreserveNewest" Visible="false" />
</ItemGroup>
</Project>

View File

@ -25,6 +25,8 @@ public class RequestKindFormatter : IMessagePackFormatter<RequestKind> {
RequestKind.Promote => "promote",
RequestKind.Update => "update",
RequestKind.Version => "version",
RequestKind.DeleteAccount => "delete_account",
RequestKind.AllowInvites => "allow_invites",
_ => throw new ArgumentOutOfRangeException(nameof(value)),
};
@ -82,6 +84,12 @@ public class RequestKindFormatter : IMessagePackFormatter<RequestKind> {
case RequestKind.Version version:
options.Resolver.GetFormatterWithVerify<VersionRequest>().Serialize(ref writer, version.Request, options);
break;
case RequestKind.DeleteAccount deleteAccount:
options.Resolver.GetFormatterWithVerify<DeleteAccountRequest>().Serialize(ref writer, deleteAccount.Request, options);
break;
case RequestKind.AllowInvites allowInvites:
options.Resolver.GetFormatterWithVerify<AllowInvitesRequest>().Serialize(ref writer, allowInvites.Request, options);
break;
}
}
@ -94,7 +102,7 @@ public class RequestKindFormatter : IMessagePackFormatter<RequestKind> {
switch (key) {
case "ping": {
var request = MessagePackSerializer.Deserialize<PingRequest>(ref reader, options);
var request = options.Resolver.GetFormatterWithVerify<PingRequest>().Deserialize(ref reader, options);
return new RequestKind.Ping(request);
}
case "authenticate": {
@ -161,6 +169,14 @@ public class RequestKindFormatter : IMessagePackFormatter<RequestKind> {
var request = options.Resolver.GetFormatterWithVerify<VersionRequest>().Deserialize(ref reader, options);
return new RequestKind.Version(request);
}
case "delete_account": {
var request = options.Resolver.GetFormatterWithVerify<DeleteAccountRequest>().Deserialize(ref reader, options);
return new RequestKind.DeleteAccount(request);
}
case "allow_invites": {
var request = options.Resolver.GetFormatterWithVerify<AllowInvitesRequest>().Deserialize(ref reader, options);
return new RequestKind.AllowInvites(request);
}
default:
throw new MessagePackSerializationException("Invalid RequestKind");
}

View File

@ -106,6 +106,14 @@ public class ResponseKindFormatter : IMessagePackFormatter<ResponseKind> {
var response = options.Resolver.GetFormatterWithVerify<AnnounceResponse>().Deserialize(ref reader, options);
return new ResponseKind.Announce(response);
}
case "delete_account": {
var response = options.Resolver.GetFormatterWithVerify<DeleteAccountResponse>().Deserialize(ref reader, options);
return new ResponseKind.DeleteAccount(response);
}
case "allow_invites": {
var response = options.Resolver.GetFormatterWithVerify<AllowInvitesResponse>().Deserialize(ref reader, options);
return new ResponseKind.AllowInvites(response);
}
default:
throw new MessagePackSerializationException("Invalid ResponseKind");
}

View File

@ -0,0 +1,17 @@
using MessagePack;
namespace ExtraChat.Protocol;
[Serializable]
[MessagePackObject]
public class AllowInvitesRequest {
[Key(0)]
public bool Allowed;
}
[Serializable]
[MessagePackObject]
public class AllowInvitesResponse {
[Key(0)]
public bool Allowed;
}

View File

@ -2,6 +2,7 @@ using MessagePack;
namespace ExtraChat.Protocol;
[Serializable]
[MessagePackObject]
public class AnnounceResponse {
[Key(0)]

View File

@ -10,4 +10,7 @@ public class AuthenticateRequest {
[Key(1)]
public byte[] PublicKey;
[Key(2)]
public bool AllowInvites;
}

View File

@ -0,0 +1,8 @@
using MessagePack;
namespace ExtraChat.Protocol;
[Serializable]
[MessagePackObject]
public class DeleteAccountRequest {
}

View File

@ -0,0 +1,8 @@
using MessagePack;
namespace ExtraChat.Protocol;
[Serializable]
[MessagePackObject]
public class DeleteAccountResponse {
}

View File

@ -57,4 +57,10 @@ public abstract record RequestKind {
[MessagePackObject]
public record Version(VersionRequest Request) : RequestKind;
[MessagePackObject]
public record DeleteAccount(DeleteAccountRequest Request) : RequestKind;
[MessagePackObject]
public record AllowInvites(AllowInvitesRequest Request) : RequestKind;
}

View File

@ -72,4 +72,10 @@ public abstract record ResponseKind {
[MessagePackObject]
public record Announce(AnnounceResponse Response) : ResponseKind;
[MessagePackObject]
public record DeleteAccount(DeleteAccountResponse Response) : ResponseKind;
[MessagePackObject]
public record AllowInvites(AllowInvitesResponse Response) : ResponseKind;
}

View File

@ -186,6 +186,23 @@ internal class PluginUi : IDisposable {
//
// ImGui.EndCombo();
// }
if (ImGui.Checkbox("Allow receiving invites", ref this.Plugin.ConfigInfo.AllowInvites)) {
anyChanged = true;
Task.Run(async () => await this.Plugin.Client.AllowInvitesToast(this.Plugin.ConfigInfo.AllowInvites));
}
if (ImGui.CollapsingHeader("Delete account")) {
if (this.Plugin.Client.Channels.Count > 0) {
ImGui.TextUnformatted("You must leave or disband all ExtraChat linkshells you are currently in before you can delete your account.");
} else {
ImGui.TextUnformatted("Clicking the button below will permanently and irreversibly delete your account from ExtraChat's servers.");
if (ImGui.Button("Delete account")) {
Task.Run(async () => await this.Plugin.Client.DeleteAccountToast());
}
}
}
}
private void DrawSettingsLinkshells(ref bool anyChanged) {