From 0e9a2e6e1c20a5b086fe77173037c9a3764d634f Mon Sep 17 00:00:00 2001 From: Vankka Date: Wed, 19 Jul 2023 00:13:00 +0300 Subject: [PATCH] Linking module, add linked/unlinked events --- .../events/linking/AccountLinkedEvent.java | 56 +++++++++++++++++++ .../events/linking/AccountUnlinkedEvent.java | 37 ++++++++++++ .../discordsrv/common/AbstractDiscordSRV.java | 2 + .../common/linking/LinkingModule.java | 30 ++++++++++ .../impl/MinecraftAuthenticationLinker.java | 26 ++++++++- 5 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 api/src/main/java/com/discordsrv/api/event/events/linking/AccountLinkedEvent.java create mode 100644 api/src/main/java/com/discordsrv/api/event/events/linking/AccountUnlinkedEvent.java create mode 100644 common/src/main/java/com/discordsrv/common/linking/LinkingModule.java diff --git a/api/src/main/java/com/discordsrv/api/event/events/linking/AccountLinkedEvent.java b/api/src/main/java/com/discordsrv/api/event/events/linking/AccountLinkedEvent.java new file mode 100644 index 00000000..0b809010 --- /dev/null +++ b/api/src/main/java/com/discordsrv/api/event/events/linking/AccountLinkedEvent.java @@ -0,0 +1,56 @@ +package com.discordsrv.api.event.events.linking; + +import com.discordsrv.api.event.events.Event; +import com.discordsrv.api.profile.IProfile; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +/** + * An event for when an account pair has been linked successfully. + */ +public class AccountLinkedEvent implements Event { + + private final IProfile profile; + + public AccountLinkedEvent(@NotNull IProfile profile) { + if (!profile.isLinked()) { + throw new IllegalStateException("Profile is not linked"); + } + this.profile = profile; + } + + /** + * The profile of the linked account pair. + * @return the profile + */ + @NotNull + public IProfile getProfile() { + return profile; + } + + /** + * The UUID of the player that was linked, this player may not be connected to the server at the time of this event. + * @return the player's {@link UUID} + */ + @NotNull + public UUID getPlayerUUID() { + UUID uuid = profile.playerUUID(); + if (uuid == null) { + throw new IllegalStateException("playerUUID is null"); + } + return uuid; + } + + /** + * The user id of the user that was linked. + * @return the user's Discord user id + */ + public long getUserId() { + Long userId = profile.userId(); + if (userId == null) { + throw new IllegalStateException("userId is null"); + } + return userId; + } +} diff --git a/api/src/main/java/com/discordsrv/api/event/events/linking/AccountUnlinkedEvent.java b/api/src/main/java/com/discordsrv/api/event/events/linking/AccountUnlinkedEvent.java new file mode 100644 index 00000000..106fccd0 --- /dev/null +++ b/api/src/main/java/com/discordsrv/api/event/events/linking/AccountUnlinkedEvent.java @@ -0,0 +1,37 @@ +package com.discordsrv.api.event.events.linking; + +import com.discordsrv.api.event.events.Event; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +/** + * An event for when an account pair has been unlinked successfully. + */ +public class AccountUnlinkedEvent implements Event { + + private final UUID playerUUID; + private final long userId; + + public AccountUnlinkedEvent(@NotNull UUID playerUUID, long userId) { + this.playerUUID = playerUUID; + this.userId = userId; + } + + /** + * The UUID of the player that was unlinked, this player may not be connected to the server at the time of this event. + * @return the player's {@link UUID} + */ + @NotNull + public UUID getPlayerUUID() { + return playerUUID; + } + + /** + * The user id of the user that was unlinked. + * @return the user's Discord user id + */ + public long getUserId() { + return userId; + } +} diff --git a/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java b/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java index 7eba8bbc..20390650 100644 --- a/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java +++ b/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java @@ -51,6 +51,7 @@ import com.discordsrv.common.function.CheckedFunction; import com.discordsrv.common.groupsync.GroupSyncModule; import com.discordsrv.common.invite.DiscordInviteModule; import com.discordsrv.common.linking.LinkProvider; +import com.discordsrv.common.linking.LinkingModule; import com.discordsrv.common.linking.impl.MemoryLinker; import com.discordsrv.common.linking.impl.MinecraftAuthenticationLinker; import com.discordsrv.common.linking.impl.StorageLinker; @@ -542,6 +543,7 @@ public abstract class AbstractDiscordSRV { + + public LinkingModule(DiscordSRV discordSRV) { + super(discordSRV, new NamedLogger(discordSRV, "LINKING")); + } + + public void linked(UUID playerUUID, long userId) { + IProfile profile = discordSRV.profileManager().getProfile(playerUUID); + if (profile == null || !profile.isLinked()) { + throw new IllegalStateException("Notified that account linked, but profile is null or unlinked"); + } + + discordSRV.eventBus().publish(new AccountLinkedEvent(profile)); + } + + public void unlinked(UUID playerUUID, long userId) { + discordSRV.eventBus().publish(new AccountUnlinkedEvent(playerUUID, userId)); + } +} diff --git a/common/src/main/java/com/discordsrv/common/linking/impl/MinecraftAuthenticationLinker.java b/common/src/main/java/com/discordsrv/common/linking/impl/MinecraftAuthenticationLinker.java index da607970..d8264d9b 100644 --- a/common/src/main/java/com/discordsrv/common/linking/impl/MinecraftAuthenticationLinker.java +++ b/common/src/main/java/com/discordsrv/common/linking/impl/MinecraftAuthenticationLinker.java @@ -23,6 +23,7 @@ import com.discordsrv.common.function.CheckedSupplier; import com.discordsrv.common.future.util.CompletableFutureUtil; import com.discordsrv.common.linking.LinkProvider; import com.discordsrv.common.linking.LinkStore; +import com.discordsrv.common.linking.LinkingModule; import com.discordsrv.common.logging.Logger; import com.discordsrv.common.logging.NamedLogger; import me.minecraftauth.lib.AuthService; @@ -80,14 +81,35 @@ public class MinecraftAuthenticationLinker extends CachedLinkProvider implements private void linked(UUID playerUUID, long userId) { logger.debug("New link: " + playerUUID + " & " + Long.toUnsignedString(userId)); - linkStore.createLink(playerUUID, userId); + linkStore.createLink(playerUUID, userId).whenComplete((v, t) -> { + if (t != null) { + logger.error("Failed to link player persistently", t); + return; + } + + module().linked(playerUUID, userId); + }); } private void unlinked(UUID playerUUID, long userId) { logger.debug("Unlink: " + playerUUID + " & " + Long.toUnsignedString(userId)); - linkStore.createLink(playerUUID, userId); + linkStore.createLink(playerUUID, userId).whenComplete((v, t) -> { + if (t != null) { + logger.error("Failed to unlink player in persistent storage", t); + return; + } + module().unlinked(playerUUID, userId); + }); + } + + private LinkingModule module() { + LinkingModule module = discordSRV.getModule(LinkingModule.class); + if (module == null) { + throw new IllegalStateException("LinkingModule not available"); + } + return module; } private CompletableFuture> query(