Account.java

package dev.aura.bungeechat.account;

import dev.aura.bungeechat.api.account.BungeeChatAccount;
import dev.aura.bungeechat.api.enums.ChannelType;
import dev.aura.bungeechat.module.BungeecordModuleManager;
import dev.aura.bungeechat.permission.Permission;
import dev.aura.bungeechat.permission.PermissionManager;
import dev.aura.bungeechat.util.DummyPlayer;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.sql.Timestamp;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;

@Data
@EqualsAndHashCode(of = "uuid")
@SuppressFBWarnings(
    value = {"JLM_JSR166_UTILCONCURRENT_MONITORENTER", "EI_EXPOSE_REP", "EI_EXPOSE_REP2"},
    justification = "Code is generated by lombok which means I don't have any influence on it.")
public class Account implements BungeeChatAccount {
  @SuppressFBWarnings(value = "MS_PKGPROTECT", justification = "protected is just right")
  protected static ChannelType defaultChannelType = ChannelType.LOCAL;

  @Getter(AccessLevel.NONE)
  @Setter(AccessLevel.NONE)
  private UUID uuid;

  @Getter(lazy = true)
  private final ProxiedPlayer proxiedPlayer =
      (ProxiedPlayer)
          BungeecordAccountManager.getCommandSender(this).orElseGet(() -> new DummyPlayer(uuid));

  private ChannelType channelType;
  private boolean vanished;

  @Getter(AccessLevel.NONE)
  private boolean messenger;

  @Getter(AccessLevel.NONE)
  private boolean socialSpy;

  @Getter(AccessLevel.NONE)
  private boolean localSpy;

  private final BlockingQueue<UUID> ignored;
  private Timestamp mutedUntil;
  private Optional<String> storedPrefix;
  private Optional<String> storedSuffix;

  protected Account(ProxiedPlayer player) {
    this(player.getUniqueId());
  }

  protected Account(UUID uuid) {
    this.uuid = uuid;
    channelType = defaultChannelType;
    vanished = false;
    messenger = true;
    socialSpy = false;
    localSpy = false;
    ignored = new LinkedBlockingQueue<>();
    mutedUntil = new Timestamp(0);
    storedPrefix = Optional.empty();
    storedSuffix = Optional.empty();
  }

  protected Account(
      UUID uuid,
      ChannelType channelType,
      boolean vanished,
      boolean messenger,
      boolean socialSpy,
      boolean localSpy,
      BlockingQueue<UUID> ignored,
      Timestamp mutedUntil,
      Optional<String> storedPrefix,
      Optional<String> storedSuffix) {
    this.uuid = uuid;
    this.channelType = channelType;
    this.vanished = vanished;
    this.messenger = messenger;
    this.socialSpy = socialSpy;
    this.localSpy = localSpy;
    this.ignored = ignored;
    this.mutedUntil = mutedUntil;
    this.storedPrefix = storedPrefix;
    this.storedSuffix = storedSuffix;
  }

  @Override
  public UUID getUniqueId() {
    return uuid;
  }

  @Override
  public ChannelType getDefaultChannelType() {
    return defaultChannelType;
  }

  @Override
  public boolean isVanished() {
    return vanished && BungeecordModuleManager.VANISHER_MODULE.isEnabled();
  }

  @Override
  public boolean hasMessengerEnabled() {
    return messenger;
  }

  @Override
  public boolean hasSocialSpyEnabled() {
    if (socialSpy && !PermissionManager.hasPermission(this, Permission.COMMAND_SOCIALSPY)) {
      setSocialSpy(false);
    }

    return socialSpy;
  }

  @Override
  public boolean hasLocalSpyEnabled() {
    if (localSpy && !PermissionManager.hasPermission(this, Permission.COMMAND_LOCALSPY)) {
      setLocalSpy(false);
    }

    return localSpy;
  }

  @Override
  public BlockingQueue<UUID> getIgnored() {
    return BungeecordModuleManager.IGNORING_MODULE.isEnabled()
        ? ignored
        : new LinkedBlockingQueue<>();
  }

  public boolean hasIgnored(ProxiedPlayer player) {
    return hasIgnored(player.getUniqueId());
  }

  @Override
  public void addIgnore(UUID uuid) {
    ignored.add(uuid);
  }

  public void addIgnore(ProxiedPlayer player) {
    this.addIgnore(player.getUniqueId());
  }

  @Override
  public void removeIgnore(UUID uuid) {
    ignored.remove(uuid);
  }

  public void removeIgnore(ProxiedPlayer player) {
    this.removeIgnore(player.getUniqueId());
  }

  @Override
  public String getName() {
    return getProxiedPlayer().getName();
  }

  @Override
  public String getDisplayName() {
    return getProxiedPlayer().getDisplayName();
  }

  @Override
  public int getPing() {
    return getProxiedPlayer().getPing();
  }

  @Override
  public String getServerName() {
    try {
      return getServerInfo().getName();
    } catch (NullPointerException e) {
      return unknownServer;
    }
  }

  @Override
  public String getServerIP() {
    try {
      return getServerInfo().getSocketAddress().toString();
    } catch (NullPointerException e) {
      return unknownServer;
    }
  }

  @SuppressFBWarnings(
      value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD",
      justification = "Rarely every used, so no issue")
  @Override
  public void setDefaultChannelType(ChannelType channelType) {
    defaultChannelType = channelType;
  }

  public static void staticSetDefaultChannelType(ChannelType channelType) {
    defaultChannelType = channelType;
  }

  @Override
  public String toString() {
    return getName();
  }

  private ServerInfo getServerInfo() {
    ProxiedPlayer player = getProxiedPlayer();
    Server server = player.getServer();

    if (server == null) return player.getReconnectServer();
    else return server.getInfo();
  }
}