mirror of
https://github.com/DiscordSRV/Ascension.git
synced 2024-11-22 11:55:54 +01:00
Improvements & fixes to AbstractSyncModule
This commit is contained in:
parent
72758ff888
commit
654bfb5907
@ -1,3 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the DiscordSRV API, licensed under the MIT License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.discordsrv.api.punishment;
|
package com.discordsrv.api.punishment;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
@ -70,6 +70,9 @@ public class BukkitBanModule extends AbstractModule<BukkitDiscordSRV> implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
return entryFuture.thenApply(ban -> {
|
return entryFuture.thenApply(ban -> {
|
||||||
|
if (ban == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Date expiration = ban.getExpiration();
|
Date expiration = ban.getExpiration();
|
||||||
return new Punishment(expiration != null ? expiration.toInstant() : null, ban.getReason(), ban.getSource());
|
return new Punishment(expiration != null ? expiration.toInstant() : null, ban.getReason(), ban.getSource());
|
||||||
});
|
});
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.discordsrv.common.bansync;
|
package com.discordsrv.common.bansync;
|
||||||
|
|
||||||
import com.discordsrv.api.discord.connection.details.DiscordGatewayIntent;
|
import com.discordsrv.api.discord.connection.details.DiscordGatewayIntent;
|
||||||
@ -71,7 +89,7 @@ public class BanSyncModule extends AbstractSyncModule<DiscordSRV, BanSyncConfig,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String logName() {
|
public String logFileName() {
|
||||||
return "bansync";
|
return "bansync";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,8 +109,10 @@ public class BanSyncModule extends AbstractSyncModule<DiscordSRV, BanSyncConfig,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isActive(Punishment state) {
|
protected @Nullable ISyncResult doesStateMatch(Punishment one, Punishment two) {
|
||||||
return state != null;
|
boolean oneActive = one != null;
|
||||||
|
boolean twoActive = two != null;
|
||||||
|
return (oneActive == twoActive) ? GenericSyncResults.both(oneActive) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PunishmentEvent upsertEvent(long userId, boolean newState) {
|
private PunishmentEvent upsertEvent(long userId, boolean newState) {
|
||||||
@ -211,7 +231,7 @@ public class BanSyncModule extends AbstractSyncModule<DiscordSRV, BanSyncConfig,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CompletableFuture<ISyncResult> applyDiscord(BanSyncConfig config, long userId, Punishment state) {
|
protected CompletableFuture<ISyncResult> applyDiscord(BanSyncConfig config, long userId, Punishment newState) {
|
||||||
if (config.direction == SyncDirection.DISCORD_TO_MINECRAFT) {
|
if (config.direction == SyncDirection.DISCORD_TO_MINECRAFT) {
|
||||||
return CompletableFuture.completedFuture(GenericSyncResults.WRONG_DIRECTION);
|
return CompletableFuture.completedFuture(GenericSyncResults.WRONG_DIRECTION);
|
||||||
}
|
}
|
||||||
@ -228,9 +248,10 @@ public class BanSyncModule extends AbstractSyncModule<DiscordSRV, BanSyncConfig,
|
|||||||
}
|
}
|
||||||
|
|
||||||
UserSnowflake snowflake = UserSnowflake.fromId(userId);
|
UserSnowflake snowflake = UserSnowflake.fromId(userId);
|
||||||
if (state != null) {
|
if (newState != null) {
|
||||||
return guild.ban(snowflake, config.discordMessageHoursToDelete, TimeUnit.HOURS)
|
return guild.ban(snowflake, config.discordMessageHoursToDelete, TimeUnit.HOURS)
|
||||||
.reason(discordSRV.placeholderService().replacePlaceholders(config.discordBanReasonFormat, state))
|
.reason(discordSRV.placeholderService().replacePlaceholders(config.discordBanReasonFormat,
|
||||||
|
newState))
|
||||||
.submit()
|
.submit()
|
||||||
.thenApply(v -> GenericSyncResults.ADD_DISCORD);
|
.thenApply(v -> GenericSyncResults.ADD_DISCORD);
|
||||||
} else {
|
} else {
|
||||||
@ -242,7 +263,7 @@ public class BanSyncModule extends AbstractSyncModule<DiscordSRV, BanSyncConfig,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CompletableFuture<ISyncResult> applyGame(BanSyncConfig config, UUID playerUUID, Punishment state) {
|
protected CompletableFuture<ISyncResult> applyGame(BanSyncConfig config, UUID playerUUID, Punishment newState) {
|
||||||
if (config.direction == SyncDirection.MINECRAFT_TO_DISCORD) {
|
if (config.direction == SyncDirection.MINECRAFT_TO_DISCORD) {
|
||||||
return CompletableFuture.completedFuture(GenericSyncResults.WRONG_DIRECTION);
|
return CompletableFuture.completedFuture(GenericSyncResults.WRONG_DIRECTION);
|
||||||
}
|
}
|
||||||
@ -252,9 +273,11 @@ public class BanSyncModule extends AbstractSyncModule<DiscordSRV, BanSyncConfig,
|
|||||||
return CompletableFuture.completedFuture(BanSyncResult.NO_PUNISHMENT_INTEGRATION);
|
return CompletableFuture.completedFuture(BanSyncResult.NO_PUNISHMENT_INTEGRATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state != null) {
|
if (newState != null) {
|
||||||
String reason = discordSRV.placeholderService().replacePlaceholders(config.gameBanReasonFormat, state);
|
String reason = discordSRV.placeholderService().replacePlaceholders(config.gameBanReasonFormat,
|
||||||
String punisher = discordSRV.placeholderService().replacePlaceholders(config.gamePunisherFormat, state);
|
newState);
|
||||||
|
String punisher = discordSRV.placeholderService().replacePlaceholders(config.gamePunisherFormat,
|
||||||
|
newState);
|
||||||
return bans.addBan(playerUUID, null, reason, punisher)
|
return bans.addBan(playerUUID, null, reason, punisher)
|
||||||
.thenApply(v -> GenericSyncResults.ADD_GAME);
|
.thenApply(v -> GenericSyncResults.ADD_GAME);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.discordsrv.common.bansync.enums;
|
package com.discordsrv.common.bansync.enums;
|
||||||
|
|
||||||
import com.discordsrv.common.sync.cause.ISyncCause;
|
import com.discordsrv.common.sync.cause.ISyncCause;
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.discordsrv.common.bansync.enums;
|
package com.discordsrv.common.bansync.enums;
|
||||||
|
|
||||||
import com.discordsrv.common.sync.result.ISyncResult;
|
import com.discordsrv.common.sync.result.ISyncResult;
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.discordsrv.common.config.main;
|
package com.discordsrv.common.config.main;
|
||||||
|
|
||||||
import com.discordsrv.common.config.main.generic.AbstractSyncConfig;
|
import com.discordsrv.common.config.main.generic.AbstractSyncConfig;
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.discordsrv.common.config.main.generic;
|
package com.discordsrv.common.config.main.generic;
|
||||||
|
|
||||||
import com.discordsrv.common.DiscordSRV;
|
import com.discordsrv.common.DiscordSRV;
|
||||||
|
@ -66,7 +66,7 @@ public class GroupSyncModule extends AbstractSyncModule<DiscordSRV, GroupSyncCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String logName() {
|
public String logFileName() {
|
||||||
return "groupsync";
|
return "groupsync";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,8 +86,11 @@ public class GroupSyncModule extends AbstractSyncModule<DiscordSRV, GroupSyncCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isActive(Boolean state) {
|
protected @Nullable ISyncResult doesStateMatch(Boolean one, Boolean two) {
|
||||||
return state;
|
if (one == two) {
|
||||||
|
return GenericSyncResults.both(one);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -154,8 +157,8 @@ public class GroupSyncModule extends AbstractSyncModule<DiscordSRV, GroupSyncCon
|
|||||||
groupChanged(player, groupName, serverContext, cause, false);
|
groupChanged(player, groupName, serverContext, cause, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void roleChanged(long userId, long roleId, boolean state) {
|
private void roleChanged(long userId, long roleId, boolean newState) {
|
||||||
if (checkExpectation(expectedDiscordChanges, userId, roleId, state)) {
|
if (checkExpectation(expectedDiscordChanges, userId, roleId, newState)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +168,7 @@ public class GroupSyncModule extends AbstractSyncModule<DiscordSRV, GroupSyncCon
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
discordChanged(GroupSyncCause.DISCORD_ROLE_CHANGE, Someone.of(userId), roleId, state);
|
discordChanged(GroupSyncCause.DISCORD_ROLE_CHANGE, Someone.of(userId), roleId, newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void groupChanged(
|
private void groupChanged(
|
||||||
@ -173,7 +176,7 @@ public class GroupSyncModule extends AbstractSyncModule<DiscordSRV, GroupSyncCon
|
|||||||
String groupName,
|
String groupName,
|
||||||
Set<String> serverContext,
|
Set<String> serverContext,
|
||||||
GroupSyncCause cause,
|
GroupSyncCause cause,
|
||||||
Boolean state
|
boolean state
|
||||||
) {
|
) {
|
||||||
if (cause.isDiscordSRVCanCause() && checkExpectation(expectedMinecraftChanges, playerUUID, groupName, state)) {
|
if (cause.isDiscordSRVCanCause() && checkExpectation(expectedMinecraftChanges, playerUUID, groupName, state)) {
|
||||||
return;
|
return;
|
||||||
@ -247,7 +250,7 @@ public class GroupSyncModule extends AbstractSyncModule<DiscordSRV, GroupSyncCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<ISyncResult> applyDiscord(GroupSyncConfig.PairConfig config, long userId, Boolean state) {
|
public CompletableFuture<ISyncResult> applyDiscord(GroupSyncConfig.PairConfig config, long userId, Boolean newState) {
|
||||||
DiscordRole role = discordSRV.discordAPI().getRoleById(config.roleId);
|
DiscordRole role = discordSRV.discordAPI().getRoleById(config.roleId);
|
||||||
if (role == null) {
|
if (role == null) {
|
||||||
return CompletableFutureUtil.failed(new SyncFail(GroupSyncResult.ROLE_DOESNT_EXIST));
|
return CompletableFutureUtil.failed(new SyncFail(GroupSyncResult.ROLE_DOESNT_EXIST));
|
||||||
@ -255,11 +258,11 @@ public class GroupSyncModule extends AbstractSyncModule<DiscordSRV, GroupSyncCon
|
|||||||
|
|
||||||
Map<Long, Boolean> expected = expectedDiscordChanges.get(userId, key -> new ConcurrentHashMap<>());
|
Map<Long, Boolean> expected = expectedDiscordChanges.get(userId, key -> new ConcurrentHashMap<>());
|
||||||
if (expected != null) {
|
if (expected != null) {
|
||||||
expected.put(config.roleId, state);
|
expected.put(config.roleId, newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
return role.getGuild().retrieveMemberById(userId)
|
return role.getGuild().retrieveMemberById(userId)
|
||||||
.thenCompose(member -> state
|
.thenCompose(member -> newState
|
||||||
? member.addRole(role).thenApply(v -> (ISyncResult) GenericSyncResults.ADD_DISCORD)
|
? member.addRole(role).thenApply(v -> (ISyncResult) GenericSyncResults.ADD_DISCORD)
|
||||||
: member.removeRole(role).thenApply(v -> GenericSyncResults.REMOVE_DISCORD)
|
: member.removeRole(role).thenApply(v -> GenericSyncResults.REMOVE_DISCORD)
|
||||||
).whenComplete((r, t) -> {
|
).whenComplete((r, t) -> {
|
||||||
@ -271,14 +274,14 @@ public class GroupSyncModule extends AbstractSyncModule<DiscordSRV, GroupSyncCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<ISyncResult> applyGame(GroupSyncConfig.PairConfig config, UUID playerUUID, Boolean state) {
|
public CompletableFuture<ISyncResult> applyGame(GroupSyncConfig.PairConfig config, UUID playerUUID, Boolean newState) {
|
||||||
Map<String, Boolean> expected = expectedMinecraftChanges.get(playerUUID, key -> new ConcurrentHashMap<>());
|
Map<String, Boolean> expected = expectedMinecraftChanges.get(playerUUID, key -> new ConcurrentHashMap<>());
|
||||||
if (expected != null) {
|
if (expected != null) {
|
||||||
expected.put(config.groupName, state);
|
expected.put(config.groupName, newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompletableFuture<ISyncResult> future =
|
CompletableFuture<ISyncResult> future =
|
||||||
state
|
newState
|
||||||
? addGroup(playerUUID, config).thenApply(v -> GenericSyncResults.ADD_GAME)
|
? addGroup(playerUUID, config).thenApply(v -> GenericSyncResults.ADD_GAME)
|
||||||
: removeGroup(playerUUID, config).thenApply(v -> GenericSyncResults.REMOVE_GAME);
|
: removeGroup(playerUUID, config).thenApply(v -> GenericSyncResults.REMOVE_GAME);
|
||||||
return future.exceptionally(t -> {
|
return future.exceptionally(t -> {
|
||||||
|
@ -178,8 +178,8 @@ public class LuckPermsIntegration extends PluginIntegration<DiscordSRV> implemen
|
|||||||
|
|
||||||
InheritanceNode node = InheritanceNode.builder(group).context(contexts).build();
|
InheritanceNode node = InheritanceNode.builder(group).context(contexts).build();
|
||||||
DataMutateResult result = function.apply(user.data(), node);
|
DataMutateResult result = function.apply(user.data(), node);
|
||||||
if (result != DataMutateResult.SUCCESS) {
|
if (!result.wasSuccessful()) {
|
||||||
return CompletableFutureUtil.failed(new MessageException(result.name()));
|
return CompletableFutureUtil.failed(new MessageException("Group mutate failed: " + result.name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return luckPerms.getUserManager().saveUser(user);
|
return luckPerms.getUserManager().saveUser(user);
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.discordsrv.common.someone;
|
package com.discordsrv.common.someone;
|
||||||
|
|
||||||
import com.discordsrv.api.discord.entity.DiscordUser;
|
import com.discordsrv.api.discord.entity.DiscordUser;
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.discordsrv.common.sync;
|
package com.discordsrv.common.sync;
|
||||||
|
|
||||||
import com.discordsrv.api.DiscordSRVApi;
|
import com.discordsrv.api.DiscordSRVApi;
|
||||||
@ -17,11 +35,12 @@ import com.discordsrv.common.sync.enums.SyncDirection;
|
|||||||
import com.discordsrv.common.sync.result.GenericSyncResults;
|
import com.discordsrv.common.sync.result.GenericSyncResults;
|
||||||
import com.discordsrv.common.sync.enums.SyncSide;
|
import com.discordsrv.common.sync.enums.SyncSide;
|
||||||
import com.discordsrv.common.sync.result.ISyncResult;
|
import com.discordsrv.common.sync.result.ISyncResult;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@ -51,17 +70,17 @@ public abstract class AbstractSyncModule<
|
|||||||
super(discordSRV, new NamedLogger(discordSRV, loggerName));
|
super(discordSRV, new NamedLogger(discordSRV, loggerName));
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract String syncName();
|
protected abstract String syncName();
|
||||||
public abstract String logName();
|
protected abstract String logFileName();
|
||||||
|
|
||||||
public abstract String gameTerm();
|
protected abstract String gameTerm();
|
||||||
public abstract String discordTerm();
|
protected abstract String discordTerm();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all in use synchronizables.
|
* Returns a list of all in use synchronizables.
|
||||||
* @return a list of configurations for synchronizables
|
* @return a list of configurations for synchronizables
|
||||||
*/
|
*/
|
||||||
public abstract List<C> configs();
|
protected abstract List<C> configs();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reload(Consumer<DiscordSRVApi.ReloadResult> resultConsumer) {
|
public void reload(Consumer<DiscordSRVApi.ReloadResult> resultConsumer) {
|
||||||
@ -131,12 +150,11 @@ public abstract class AbstractSyncModule<
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the provided state is active or inactive, should this not match for the state of the two sides, synchronization will occur.
|
* Checks if the given new and current state are the same, basically meaning that no update is necessary.
|
||||||
*
|
* @return the result stating the states are the same, otherwise {@code null} to state they are not
|
||||||
* @param state the state
|
|
||||||
* @return {@code true} indicating the provided state is "active"
|
|
||||||
*/
|
*/
|
||||||
protected abstract boolean isActive(S state);
|
@Nullable
|
||||||
|
protected abstract ISyncResult doesStateMatch(S one, S two);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current state of the provided config for the specified user on Discord.
|
* Gets the current state of the provided config for the specified user on Discord.
|
||||||
@ -161,18 +179,18 @@ public abstract class AbstractSyncModule<
|
|||||||
*
|
*
|
||||||
* @param config the configuration for the synchronizable
|
* @param config the configuration for the synchronizable
|
||||||
* @param userId the Discord user id
|
* @param userId the Discord user id
|
||||||
* @param state the state to apply
|
* @param newState the newState to apply
|
||||||
* @return a future with the result of the synchronization
|
* @return a future with the result of the synchronization
|
||||||
*/
|
*/
|
||||||
protected abstract CompletableFuture<ISyncResult> applyDiscord(C config, long userId, S state);
|
protected abstract CompletableFuture<ISyncResult> applyDiscord(C config, long userId, S newState);
|
||||||
|
|
||||||
protected CompletableFuture<ISyncResult> applyDiscordIfNot(C config, long userId, S state) {
|
protected CompletableFuture<ISyncResult> applyDiscordIfDoesNotMatch(C config, long userId, S newState) {
|
||||||
return getDiscord(config, userId).thenCompose(value -> {
|
return getDiscord(config, userId).thenCompose(currentState -> {
|
||||||
boolean actualValue;
|
ISyncResult result = doesStateMatch(newState, currentState);
|
||||||
if ((actualValue = isActive(state)) == isActive(value)) {
|
if (result != null) {
|
||||||
return CompletableFuture.completedFuture(actualValue ? GenericSyncResults.BOTH_TRUE : GenericSyncResults.BOTH_FALSE);
|
return CompletableFuture.completedFuture(result);
|
||||||
} else {
|
} else {
|
||||||
return applyDiscord(config, userId, state);
|
return applyDiscord(config, userId, newState);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -182,23 +200,23 @@ public abstract class AbstractSyncModule<
|
|||||||
*
|
*
|
||||||
* @param config the configuration for the synchronizable
|
* @param config the configuration for the synchronizable
|
||||||
* @param playerUUID the Minecraft player {@link UUID}
|
* @param playerUUID the Minecraft player {@link UUID}
|
||||||
* @param state the state to apply
|
* @param newState the newState to apply
|
||||||
* @return a future with the result of the synchronization
|
* @return a future with the result of the synchronization
|
||||||
*/
|
*/
|
||||||
protected abstract CompletableFuture<ISyncResult> applyGame(C config, UUID playerUUID, S state);
|
protected abstract CompletableFuture<ISyncResult> applyGame(C config, UUID playerUUID, S newState);
|
||||||
|
|
||||||
protected CompletableFuture<ISyncResult> applyGameIfNot(C config, UUID playerUUID, S state) {
|
protected CompletableFuture<ISyncResult> applyGameIfDoesNotMatch(C config, UUID playerUUID, S newState) {
|
||||||
return getGame(config, playerUUID).thenCompose(value -> {
|
return getGame(config, playerUUID).thenCompose(currentState -> {
|
||||||
boolean active;
|
ISyncResult result = doesStateMatch(currentState, newState);
|
||||||
if ((active = isActive(state)) == isActive(value)) {
|
if (result != null) {
|
||||||
return CompletableFuture.completedFuture(active ? GenericSyncResults.BOTH_TRUE : GenericSyncResults.BOTH_FALSE);
|
return CompletableFuture.completedFuture(result);
|
||||||
} else {
|
} else {
|
||||||
return applyGame(config, playerUUID, state);
|
return applyGame(config, playerUUID, newState);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CompletableFuture<SyncSummary<C>> discordChanged(ISyncCause cause, Someone someone, D discordId, S state) {
|
protected CompletableFuture<SyncSummary<C>> discordChanged(ISyncCause cause, Someone someone, D discordId, S newState) {
|
||||||
List<C> gameConfigs = configsForDiscord.get(discordId);
|
List<C> gameConfigs = configsForDiscord.get(discordId);
|
||||||
if (gameConfigs == null) {
|
if (gameConfigs == null) {
|
||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
@ -206,10 +224,10 @@ public abstract class AbstractSyncModule<
|
|||||||
|
|
||||||
return someone.withLinkedAccounts(discordSRV).thenApply(resolved -> {
|
return someone.withLinkedAccounts(discordSRV).thenApply(resolved -> {
|
||||||
if (resolved == null) {
|
if (resolved == null) {
|
||||||
return new SyncSummary<C>(cause, someone).fail(GenericSyncResults.NOT_LINKED);
|
return new SyncSummary<>(this, cause, someone).fail(GenericSyncResults.NOT_LINKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
SyncSummary<C> summary = new SyncSummary<>(cause, resolved);
|
SyncSummary<C> summary = new SyncSummary<>(this, cause, resolved);
|
||||||
for (C config : gameConfigs) {
|
for (C config : gameConfigs) {
|
||||||
SyncDirection direction = config.direction;
|
SyncDirection direction = config.direction;
|
||||||
if (direction == SyncDirection.MINECRAFT_TO_DISCORD) {
|
if (direction == SyncDirection.MINECRAFT_TO_DISCORD) {
|
||||||
@ -218,7 +236,7 @@ public abstract class AbstractSyncModule<
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
summary.appendResult(config, applyGameIfNot(config, resolved.playerUUID(), state));
|
summary.appendResult(config, applyGameIfDoesNotMatch(config, resolved.playerUUID(), newState));
|
||||||
|
|
||||||
// If the sync is bidirectional, also sync anything else linked to the same Minecraft id
|
// If the sync is bidirectional, also sync anything else linked to the same Minecraft id
|
||||||
if (direction == SyncDirection.DISCORD_TO_MINECRAFT) {
|
if (direction == SyncDirection.DISCORD_TO_MINECRAFT) {
|
||||||
@ -231,11 +249,11 @@ public abstract class AbstractSyncModule<
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (C gameConfig : discordConfigs) {
|
for (C gameConfig : discordConfigs) {
|
||||||
if (gameConfig.discordId() == discordId) {
|
if (Objects.equals(gameConfig.discordId(), discordId)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
summary.appendResult(gameConfig, applyDiscordIfNot(gameConfig, resolved.userId(), state));
|
summary.appendResult(gameConfig, applyDiscordIfDoesNotMatch(gameConfig, resolved.userId(), newState));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return summary;
|
return summary;
|
||||||
@ -246,7 +264,7 @@ public abstract class AbstractSyncModule<
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CompletableFuture<SyncSummary<C>> gameChanged(ISyncCause cause, Someone someone, G gameId, S state) {
|
protected CompletableFuture<SyncSummary<C>> gameChanged(ISyncCause cause, Someone someone, G gameId, S newState) {
|
||||||
List<C> discordConfigs = configsForGame.get(gameId);
|
List<C> discordConfigs = configsForGame.get(gameId);
|
||||||
if (discordConfigs == null) {
|
if (discordConfigs == null) {
|
||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
@ -254,10 +272,10 @@ public abstract class AbstractSyncModule<
|
|||||||
|
|
||||||
return someone.withLinkedAccounts(discordSRV).thenApply(resolved -> {
|
return someone.withLinkedAccounts(discordSRV).thenApply(resolved -> {
|
||||||
if (resolved == null) {
|
if (resolved == null) {
|
||||||
return new SyncSummary<C>(cause, someone).fail(GenericSyncResults.NOT_LINKED);
|
return new SyncSummary<>(this, cause, someone).fail(GenericSyncResults.NOT_LINKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
SyncSummary<C> summary = new SyncSummary<>(cause, resolved);
|
SyncSummary<C> summary = new SyncSummary<>(this, cause, resolved);
|
||||||
for (C config : discordConfigs) {
|
for (C config : discordConfigs) {
|
||||||
SyncDirection direction = config.direction;
|
SyncDirection direction = config.direction;
|
||||||
if (direction == SyncDirection.DISCORD_TO_MINECRAFT) {
|
if (direction == SyncDirection.DISCORD_TO_MINECRAFT) {
|
||||||
@ -266,7 +284,7 @@ public abstract class AbstractSyncModule<
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
summary.appendResult(config, applyDiscordIfNot(config, resolved.userId(), state));
|
summary.appendResult(config, applyDiscordIfDoesNotMatch(config, resolved.userId(), newState));
|
||||||
|
|
||||||
// If the sync is bidirectional, also sync anything else linked to the same Discord id
|
// If the sync is bidirectional, also sync anything else linked to the same Discord id
|
||||||
if (direction == SyncDirection.MINECRAFT_TO_DISCORD) {
|
if (direction == SyncDirection.MINECRAFT_TO_DISCORD) {
|
||||||
@ -279,11 +297,11 @@ public abstract class AbstractSyncModule<
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (C gameConfig : gameConfigs) {
|
for (C gameConfig : gameConfigs) {
|
||||||
if (gameConfig.gameId() == gameId) {
|
if (Objects.equals(gameConfig.gameId(), gameId)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
summary.appendResult(gameConfig, applyGameIfNot(gameConfig, resolved.playerUUID(), state));
|
summary.appendResult(gameConfig, applyGameIfDoesNotMatch(gameConfig, resolved.playerUUID(), newState));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return summary;
|
return summary;
|
||||||
@ -297,11 +315,11 @@ public abstract class AbstractSyncModule<
|
|||||||
public CompletableFuture<SyncSummary<C>> resyncAll(ISyncCause cause, Someone someone) {
|
public CompletableFuture<SyncSummary<C>> resyncAll(ISyncCause cause, Someone someone) {
|
||||||
return someone.withLinkedAccounts(discordSRV).thenApply(resolved -> {
|
return someone.withLinkedAccounts(discordSRV).thenApply(resolved -> {
|
||||||
if (resolved == null) {
|
if (resolved == null) {
|
||||||
return new SyncSummary<C>(cause, someone).fail(GenericSyncResults.NOT_LINKED);
|
return new SyncSummary<>(this, cause, someone).fail(GenericSyncResults.NOT_LINKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
SyncSummary<C> summary = new SyncSummary<>(cause, resolved);
|
SyncSummary<C> summary = new SyncSummary<>(this, cause, resolved);
|
||||||
List<C> configs = configs();
|
Set<C> configs = syncs.keySet();
|
||||||
|
|
||||||
for (C config : configs) {
|
for (C config : configs) {
|
||||||
summary.appendResult(config, resync(config, resolved));
|
summary.appendResult(config, resync(config, resolved));
|
||||||
@ -317,10 +335,10 @@ public abstract class AbstractSyncModule<
|
|||||||
protected CompletableFuture<SyncSummary<C>> resync(ISyncCause cause, C config, Someone someone) {
|
protected CompletableFuture<SyncSummary<C>> resync(ISyncCause cause, C config, Someone someone) {
|
||||||
return someone.withLinkedAccounts(discordSRV).thenApply(resolved -> {
|
return someone.withLinkedAccounts(discordSRV).thenApply(resolved -> {
|
||||||
if (resolved == null) {
|
if (resolved == null) {
|
||||||
return new SyncSummary<C>(cause, someone).fail(GenericSyncResults.NOT_LINKED);
|
return new SyncSummary<>(this, cause, someone).fail(GenericSyncResults.NOT_LINKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SyncSummary<C>(cause, resolved)
|
return new SyncSummary<C>(this, cause, resolved)
|
||||||
.appendResult(config, resync(config, resolved));
|
.appendResult(config, resync(config, resolved));
|
||||||
}).whenComplete((summary, t) -> {
|
}).whenComplete((summary, t) -> {
|
||||||
if (summary != null) {
|
if (summary != null) {
|
||||||
@ -340,10 +358,9 @@ public abstract class AbstractSyncModule<
|
|||||||
S gameState = gameGet.join();
|
S gameState = gameGet.join();
|
||||||
S discordState = discordGet.join();
|
S discordState = discordGet.join();
|
||||||
|
|
||||||
boolean bothState;
|
ISyncResult alreadyInSyncResult = doesStateMatch(gameState, discordState);
|
||||||
if ((bothState = (gameState != null)) == (discordState != null)) {
|
if (alreadyInSyncResult != null) {
|
||||||
// Already in sync
|
return CompletableFuture.completedFuture(alreadyInSyncResult);
|
||||||
return CompletableFuture.completedFuture((ISyncResult) (bothState ? GenericSyncResults.BOTH_TRUE : GenericSyncResults.BOTH_FALSE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SyncSide side = config.tieBreaker;
|
SyncSide side = config.tieBreaker;
|
||||||
@ -392,45 +409,71 @@ public abstract class AbstractSyncModule<
|
|||||||
|
|
||||||
private String formatResults(SyncSummary<C> summary, List<String> results) {
|
private String formatResults(SyncSummary<C> summary, List<String> results) {
|
||||||
int count = results.size();
|
int count = results.size();
|
||||||
return summary.who().toString()
|
return summary.who() + " (sync cause: " + summary.cause() + ")"
|
||||||
+ (count == 1 ? ": " : "\n")
|
+ (count == 1 ? ": " : "\n")
|
||||||
+ String.join("\n", results);
|
+ String.join("\n", results);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logSummary(SyncSummary<C> summary) {
|
private void logSummary(SyncSummary<C> summary) {
|
||||||
summary.resultFuture().whenComplete((results, t) -> {
|
summary.resultFuture().whenComplete((results, t) -> {
|
||||||
|
Throwable throwableToLog = null;
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
logger().error("Failed to " + syncName() + " " + summary.who(), t);
|
while (t instanceof CompletionException) {
|
||||||
return;
|
t = t.getCause();
|
||||||
|
}
|
||||||
|
if (t instanceof SyncFail) {
|
||||||
|
SyncFail fail = (SyncFail) t;
|
||||||
|
summary.fail(fail.getResult());
|
||||||
|
throwableToLog = fail.getCause();
|
||||||
|
} else {
|
||||||
|
logger().error("Failed to " + syncName() + " " + summary.who() + " (sync cause: " + summary.cause() + ")", t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ISyncResult allFailReason = summary.allFailReason();
|
ISyncResult allFailReason = summary.allFailReason();
|
||||||
if (allFailReason != null) {
|
if (allFailReason != null) {
|
||||||
String reason = allFailReason.format(gameTerm(), discordTerm());
|
String reason = allFailReason.format(gameTerm(), discordTerm());
|
||||||
logger().debug("Failed to " + syncName() + " " + summary.who() + ": " + reason);
|
String message = "Failed to " + syncName() + " " + summary.who() + " (sync cause: " + summary.cause() + "): " + reason;
|
||||||
|
if (!allFailReason.isSuccess()) {
|
||||||
|
logger().error(message, throwableToLog);
|
||||||
|
} else {
|
||||||
|
logger().debug(message, throwableToLog);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> logResults = new ArrayList<>();
|
Map<ISyncResult, List<String>> groupedResults = new LinkedHashMap<>();
|
||||||
List<String> auditResults = new ArrayList<>();
|
|
||||||
for (Map.Entry<C, ISyncResult> entry : results.entrySet()) {
|
for (Map.Entry<C, ISyncResult> entry : results.entrySet()) {
|
||||||
C config = entry.getKey();
|
C config = entry.getKey();
|
||||||
ISyncResult result = entry.getValue();
|
ISyncResult result = entry.getValue();
|
||||||
|
|
||||||
String log = config.describe();
|
groupedResults.computeIfAbsent(result, key -> new ArrayList<>()).add(config.describe());
|
||||||
if (StringUtils.isEmpty(log)) {
|
}
|
||||||
log += ": ";
|
|
||||||
}
|
|
||||||
log += result.format(gameTerm(), discordTerm());
|
|
||||||
|
|
||||||
logResults.add(log);
|
List<String> successResults = new ArrayList<>();
|
||||||
|
List<String> failResults = new ArrayList<>();
|
||||||
|
for (Map.Entry<ISyncResult, List<String>> entry : groupedResults.entrySet()) {
|
||||||
|
ISyncResult result = entry.getKey();
|
||||||
|
String line = result.format(gameTerm(), discordTerm())
|
||||||
|
+ ": [" + String.join(", ", entry.getValue()) + "]";
|
||||||
if (result.isSuccess()) {
|
if (result.isSuccess()) {
|
||||||
auditResults.add(log);
|
successResults.add(line);
|
||||||
|
} else {
|
||||||
|
failResults.add(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger().debug(formatResults(summary, logResults));
|
boolean anySuccess = !successResults.isEmpty();
|
||||||
discordSRV.logger().writeLogForCurrentDay(logName(), formatResults(summary, auditResults));
|
boolean anyFail = !failResults.isEmpty();
|
||||||
|
String partially = anySuccess && anyFail ? " partially" : "";
|
||||||
|
if (anySuccess) {
|
||||||
|
logger().debug(syncName() + partially + " succeeded for " + formatResults(summary, successResults));
|
||||||
|
}
|
||||||
|
if (anyFail) {
|
||||||
|
logger().error(syncName() + partially + " failed for " + formatResults(summary, failResults));
|
||||||
|
}
|
||||||
|
discordSRV.logger().writeLogForCurrentDay(logFileName(), formatResults(summary, successResults));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.discordsrv.common.sync;
|
package com.discordsrv.common.sync;
|
||||||
|
|
||||||
import com.discordsrv.common.sync.result.ISyncResult;
|
import com.discordsrv.common.sync.result.ISyncResult;
|
||||||
|
@ -1,5 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.discordsrv.common.sync;
|
package com.discordsrv.common.sync;
|
||||||
|
|
||||||
|
import com.discordsrv.common.DiscordSRV;
|
||||||
import com.discordsrv.common.config.main.generic.AbstractSyncConfig;
|
import com.discordsrv.common.config.main.generic.AbstractSyncConfig;
|
||||||
import com.discordsrv.common.future.util.CompletableFutureUtil;
|
import com.discordsrv.common.future.util.CompletableFutureUtil;
|
||||||
import com.discordsrv.common.someone.Someone;
|
import com.discordsrv.common.someone.Someone;
|
||||||
@ -9,16 +28,19 @@ import com.discordsrv.common.sync.result.ISyncResult;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class SyncSummary<C extends AbstractSyncConfig<C, ?, ?>> {
|
public class SyncSummary<C extends AbstractSyncConfig<C, ?, ?>> {
|
||||||
|
|
||||||
|
private final AbstractSyncModule<? extends DiscordSRV, C, ?, ?, ?> syncModule;
|
||||||
private final ISyncCause cause;
|
private final ISyncCause cause;
|
||||||
private final Someone who;
|
private final Someone who;
|
||||||
private ISyncResult allFailReason;
|
private ISyncResult allFailReason;
|
||||||
private final Map<C, CompletableFuture<ISyncResult>> results = new ConcurrentHashMap<>();
|
private final Map<C, CompletableFuture<ISyncResult>> results = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public SyncSummary(ISyncCause cause, Someone who) {
|
public SyncSummary(AbstractSyncModule<? extends DiscordSRV, C, ?, ?, ?> syncModule, ISyncCause cause, Someone who) {
|
||||||
|
this.syncModule = syncModule;
|
||||||
this.cause = cause;
|
this.cause = cause;
|
||||||
this.who = who;
|
this.who = who;
|
||||||
}
|
}
|
||||||
@ -55,7 +77,25 @@ public class SyncSummary<C extends AbstractSyncConfig<C, ?, ?>> {
|
|||||||
.thenApply((__) -> {
|
.thenApply((__) -> {
|
||||||
Map<C, ISyncResult> results = new HashMap<>();
|
Map<C, ISyncResult> results = new HashMap<>();
|
||||||
for (Map.Entry<C, CompletableFuture<ISyncResult>> entry : this.results.entrySet()) {
|
for (Map.Entry<C, CompletableFuture<ISyncResult>> entry : this.results.entrySet()) {
|
||||||
results.put(entry.getKey(), entry.getValue().join());
|
results.put(entry.getKey(), entry.getValue().exceptionally(t -> {
|
||||||
|
while (t instanceof CompletionException) {
|
||||||
|
t = t.getCause();
|
||||||
|
}
|
||||||
|
Throwable throwableToLog = t;
|
||||||
|
ISyncResult result = null;
|
||||||
|
if (t instanceof SyncFail) {
|
||||||
|
throwableToLog = t.getCause();
|
||||||
|
result = ((SyncFail) t).getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (throwableToLog != null) {
|
||||||
|
syncModule.logger().error(
|
||||||
|
"Error in " + syncModule.syncName() + " "
|
||||||
|
+ entry.getKey().describe() + " for " + who()
|
||||||
|
+ " (sync cause: " + cause() + ")", throwableToLog);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}).join());
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
});
|
});
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.discordsrv.common.sync.cause;
|
package com.discordsrv.common.sync.cause;
|
||||||
|
|
||||||
public enum GenericSyncCauses implements ISyncCause {
|
public enum GenericSyncCauses implements ISyncCause {
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.discordsrv.common.sync.cause;
|
package com.discordsrv.common.sync.cause;
|
||||||
|
|
||||||
public interface ISyncCause {
|
public interface ISyncCause {
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.discordsrv.common.sync.result;
|
package com.discordsrv.common.sync.result;
|
||||||
|
|
||||||
public enum GenericSyncResults implements ISyncResult {
|
public enum GenericSyncResults implements ISyncResult {
|
||||||
@ -18,6 +36,10 @@ public enum GenericSyncResults implements ISyncResult {
|
|||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
public static GenericSyncResults both(boolean value) {
|
||||||
|
return value ? BOTH_TRUE : BOTH_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
private final String message;
|
private final String message;
|
||||||
private final boolean success;
|
private final boolean success;
|
||||||
|
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||||
|
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.discordsrv.common.sync.result;
|
package com.discordsrv.common.sync.result;
|
||||||
|
|
||||||
import com.discordsrv.api.placeholder.util.Placeholders;
|
import com.discordsrv.api.placeholder.util.Placeholders;
|
||||||
|
Loading…
Reference in New Issue
Block a user