Skip to content

Commit 67101c8

Browse files
CitralFlocoderabbitai[bot]Rollczi
authored
GH-870 Add /msgtoggle command (#896)
* Innit commit * In progress: add messages, setup methods and commands * Add msgToggle repo, service, API and commands * Fix logic * Fix logic, rename messages * Remove comments * Delete duplicated message. * Update eternalcore-api/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggle.java Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Delete duplicated message. * Fix coderabbit issue * Fix naming and logic. * Resolve @imDMK review * Add comments to api * Resolve Rollcz's review * Resolve coderabbit review * Update README.md * Fix logic: enable -> enable priv messages. * Resolve @coderabbitai nitpick comment, simplify command and api * Refactor names of variables following vLuckyyy comment * Change name from toggleState to State * Simplify logic (i hope @Rollczi will like it) refactor to PrivateChatState instead of toggle * Resolve master changes * Resolve @coderabbitai 's review * Cleanup method and parameters names. Remove unused classes. * Simplify commands * Fix command messages --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Rollczi <[email protected]>
1 parent 477361c commit 67101c8

File tree

12 files changed

+322
-11
lines changed

12 files changed

+322
-11
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Get the latest development builds from our [GitHub Actions](https://github.com/E
4040
- Chat On/Off Switch
4141
- Chat Slow Mode
4242
- /ignore and /unignore (with -all option)
43-
- /msg, /socialspy, and /reply commands
43+
- /msg, /msgtoggle, /socialspy, and /reply commands
4444
- /helpop command
4545
- Advanced Notification System allowing you to customize every message to your liking (Title, Subtitle, Actionbar, Chat, etc.)
4646
- :hammer: Open Utility Blocks with simple commands like `/workbench`
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.eternalcode.core.feature.privatechat.toggle;
2+
3+
/**
4+
* Enum representing state of blocking incoming private messages by the player.
5+
*/
6+
public enum PrivateChatState {
7+
8+
/**
9+
* Player can receive private messages.
10+
*/
11+
ENABLE,
12+
13+
/**
14+
* Player cannot receive private messages.
15+
*/
16+
DISABLE;
17+
18+
PrivateChatState invert() {
19+
return this == ENABLE ? DISABLE : ENABLE;
20+
}
21+
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.eternalcode.core.feature.privatechat.toggle;
2+
3+
import java.util.UUID;
4+
import java.util.concurrent.CompletableFuture;
5+
6+
/**
7+
* This Service manages player's receiving of private messages
8+
*/
9+
public interface PrivateChatStateService {
10+
11+
/**
12+
* Checks status of player's private chat messages blocking.
13+
*
14+
* @param playerUniqueId player's UUID.
15+
* @return state of player's private chat messages blocking.
16+
*/
17+
CompletableFuture<PrivateChatState> getChatState(UUID playerUniqueId);
18+
19+
/**
20+
* Sets blocking of incoming private messages.
21+
*
22+
* @param playerUniqueId player's UUID.
23+
* @param state desired state of player's private chat messages blocking.
24+
*/
25+
CompletableFuture<Void> setChatState(UUID playerUniqueId, PrivateChatState state);
26+
27+
28+
/**
29+
* Toggle blocking of incoming private messages.
30+
*
31+
* @param playerUniqueId player's UUID.
32+
* @return new state of player's private chat messages blocking.
33+
*/
34+
CompletableFuture<PrivateChatState> toggleChatState(UUID playerUniqueId);
35+
36+
}

eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/PrivateChatServiceImpl.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.eternalcode.core.event.EventCaller;
44
import com.eternalcode.core.feature.ignore.IgnoreService;
5+
import com.eternalcode.core.feature.privatechat.toggle.PrivateChatStateService;
6+
import com.eternalcode.core.feature.privatechat.toggle.PrivateChatState;
57
import com.eternalcode.core.injector.annotations.Inject;
68
import com.eternalcode.core.injector.annotations.component.Service;
79
import com.eternalcode.core.notice.NoticeService;
@@ -24,6 +26,7 @@ class PrivateChatServiceImpl implements PrivateChatService {
2426
private final UserManager userManager;
2527
private final PrivateChatPresenter presenter;
2628
private final EventCaller eventCaller;
29+
private final PrivateChatStateService privateChatStateService;
2730

2831
private final Cache<UUID, UUID> replies = CacheBuilder.newBuilder()
2932
.expireAfterWrite(Duration.ofHours(1))
@@ -36,12 +39,14 @@ class PrivateChatServiceImpl implements PrivateChatService {
3639
NoticeService noticeService,
3740
IgnoreService ignoreService,
3841
UserManager userManager,
39-
EventCaller eventCaller
42+
EventCaller eventCaller,
43+
PrivateChatStateService privateChatStateService
4044
) {
4145
this.noticeService = noticeService;
4246
this.ignoreService = ignoreService;
4347
this.userManager = userManager;
4448
this.eventCaller = eventCaller;
49+
this.privateChatStateService = privateChatStateService;
4550

4651
this.presenter = new PrivateChatPresenter(noticeService);
4752
}
@@ -53,15 +58,25 @@ void privateMessage(User sender, User target, String message) {
5358
return;
5459
}
5560

56-
this.ignoreService.isIgnored(target.getUniqueId(), sender.getUniqueId()).thenAccept(isIgnored -> {
57-
if (!isIgnored) {
58-
this.replies.put(target.getUniqueId(), sender.getUniqueId());
59-
this.replies.put(sender.getUniqueId(), target.getUniqueId());
61+
UUID uniqueId = target.getUniqueId();
62+
63+
this.privateChatStateService.getChatState(uniqueId).thenAccept(privateChatState -> {
64+
if (privateChatState == PrivateChatState.DISABLE) {
65+
this.noticeService.player(sender.getUniqueId(), translation -> translation.privateChat().receiverDisabledMessages());
66+
67+
return;
6068
}
6169

62-
PrivateChatEvent event = new PrivateChatEvent(sender.getUniqueId(), target.getUniqueId(), message);
63-
this.eventCaller.callEvent(event);
64-
this.presenter.onPrivate(new PrivateMessage(sender, target, event.getContent(), this.socialSpy, isIgnored));
70+
this.ignoreService.isIgnored(uniqueId, sender.getUniqueId()).thenAccept(isIgnored -> {
71+
if (!isIgnored) {
72+
this.replies.put(uniqueId, sender.getUniqueId());
73+
this.replies.put(sender.getUniqueId(), uniqueId);
74+
}
75+
76+
PrivateChatEvent event = new PrivateChatEvent(sender.getUniqueId(), uniqueId, message);
77+
this.eventCaller.callEvent(event);
78+
this.presenter.onPrivate(new PrivateMessage(sender, target, event.getContent(), this.socialSpy, isIgnored));
79+
});
6580
});
6681
}
6782

eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/messages/ENPrivateMessages.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ public class ENPrivateMessages implements PrivateChatMessages {
2424
public Notice socialSpyMessage = Notice.chat(
2525
"<dark_gray>[<red>ss<dark_gray>] <dark_gray>[<gray>{SENDER} -> <white>{TARGET}<dark_gray>]<gray>: <white>{MESSAGE}");
2626

27+
public Notice receiverDisabledMessages = Notice.chat("<red>► <dark_red>This player has disabled private messages!");
28+
29+
public Notice selfMessagesDisabled = Notice.chat("<green>► <white>Private messages have been <red>disabled<white>!");
30+
public Notice selfMessagesEnabled = Notice.chat("<green>► <white>Private messages have been <green>enabled<white>!");
31+
32+
@Description("# {PLAYER} - Player")
33+
public Notice otherMessagesDisabled = Notice.chat("<green>► <white>Private messages have been <red>disabled <white>for <green>{PLAYER}<white>!");
34+
public Notice otherMessagesEnabled = Notice.chat("<green>► <white>Private messages have been <green>enabled <white>for <green>{PLAYER}<white>!");
35+
2736
@Description(" ")
2837
public Notice socialSpyEnable = Notice.chat("<green>► <white>SocialSpy has been {STATE}<white>!");
2938
public Notice socialSpyDisable = Notice.chat("<red>► <white>SocialSpy has been {STATE}<white>!");
@@ -39,10 +48,10 @@ public class ENPrivateMessages implements PrivateChatMessages {
3948
public Notice alreadyIgnorePlayer = Notice.chat("<red>► <dark_red>You already ignore this player!");
4049

4150
@Description("# {PLAYER} - Unignored player")
42-
public Notice unIgnorePlayer = Notice.chat("<red>► <dark_red>{PLAYER} <red>player has been uningored!");
51+
public Notice unIgnorePlayer = Notice.chat("<red>► <dark_red>{PLAYER} <red>player has been unignored!");
4352

4453
@Description(" ")
45-
public Notice unIgnoreAll = Notice.chat("<red>► <dark_red>All players have been uningored!");
54+
public Notice unIgnoreAll = Notice.chat("<red>► <dark_red>All players have been unignored!");
4655
public Notice cantUnIgnoreYourself = Notice.chat("<red>► <dark_red>You can't unignore yourself!");
4756

4857
@Description({" ", "# {PLAYER} - Ignored player"})

eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/messages/PLPrivateChatMessages.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ public class PLPrivateChatMessages implements PrivateChatMessages {
2929
public Notice socialSpyEnable = Notice.chat("<green>► <white>SocialSpy został {STATE}<white>!");
3030
public Notice socialSpyDisable = Notice.chat("<red>► <white>SocialSpy został {STATE}<white>!");
3131

32+
public Notice receiverDisabledMessages = Notice.chat("<red>► <dark_red>Wiadomości prywatne zostały wyłączone!");
33+
34+
public Notice selfMessagesDisabled = Notice.chat("<green>► <white>Wiadomości prywatne zostały <red>wyłączone!");
35+
public Notice selfMessagesEnabled = Notice.chat("<green>► <white>Wiadomości prywatne zostały <green>włączone!");
36+
37+
@Description({" ", "# {PLAYER} - Gracz któremu wyłączono wiadomości prywatne"})
38+
public Notice otherMessagesDisabled = Notice.chat("<green>► <white>Wiadomości prywatne zostały <red>wyłączone <white>dla gracza <green>{PLAYER}<white>!");
39+
public Notice otherMessagesEnabled = Notice.chat("<green>► <white>Wiadomości prywatne zostały <green>włączone <white>dla gracza <green>{PLAYER}<white>!");
40+
3241
@Description({" ", "# {PLAYER} - Gracz który jest zignorowany"})
3342
public Notice ignorePlayer = Notice.chat("<green>► <white>Zignorowano gracza <red>{PLAYER}<white>!");
3443

eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/messages/PrivateChatMessages.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ public interface PrivateChatMessages {
1111
Notice socialSpyEnable();
1212
Notice socialSpyDisable();
1313

14+
Notice receiverDisabledMessages();
15+
Notice selfMessagesDisabled();
16+
Notice selfMessagesEnabled();
17+
Notice otherMessagesDisabled();
18+
Notice otherMessagesEnabled();
19+
1420
Notice ignorePlayer();
1521
Notice ignoreAll();
1622
Notice unIgnorePlayer();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.eternalcode.core.feature.privatechat.toggle;
2+
3+
import com.eternalcode.annotations.scan.command.DescriptionDocs;
4+
import com.eternalcode.core.injector.annotations.Inject;
5+
import com.eternalcode.core.notice.NoticeService;
6+
import dev.rollczi.litecommands.annotations.argument.Arg;
7+
import dev.rollczi.litecommands.annotations.command.Command;
8+
import dev.rollczi.litecommands.annotations.context.Context;
9+
import dev.rollczi.litecommands.annotations.execute.Execute;
10+
import dev.rollczi.litecommands.annotations.permission.Permission;
11+
import java.util.UUID;
12+
import org.bukkit.command.CommandSender;
13+
import org.bukkit.entity.Player;
14+
15+
@Command(name = "msgtoggle")
16+
@Permission("eternalcore.msgtoggle")
17+
class PrivateChatStateCommand {
18+
19+
private final PrivateChatStateService privateChatStateService;
20+
private final NoticeService noticeService;
21+
22+
@Inject
23+
PrivateChatStateCommand(PrivateChatStateService privateChatStateService, NoticeService noticeService) {
24+
this.privateChatStateService = privateChatStateService;
25+
this.noticeService = noticeService;
26+
}
27+
28+
@Execute
29+
@DescriptionDocs(description = "Toggle receiving private messages")
30+
void execute(@Context Player sender) {
31+
UUID player = sender.getUniqueId();
32+
this.privateChatStateService.toggleChatState(player)
33+
.thenAccept(toggledState -> noticePlayer(toggledState, player));
34+
}
35+
36+
@Execute
37+
@DescriptionDocs(description = "Switch receiving private messages", arguments = "<state>")
38+
void execute(@Context Player sender, @Arg PrivateChatState state) {
39+
UUID player = sender.getUniqueId();
40+
this.privateChatStateService.setChatState(player, state)
41+
.thenAccept(ignored -> noticePlayer(state, player));
42+
}
43+
44+
@Execute
45+
@Permission("eternalcore.msgtoggle.other")
46+
@DescriptionDocs(description = "Switch receiving private messages for other player", arguments = "<player>")
47+
void other(@Context CommandSender sender, @Arg Player target) {
48+
UUID player = target.getUniqueId();
49+
this.privateChatStateService.toggleChatState(player)
50+
.thenAccept(toggledState -> noticeOtherPlayer(sender, toggledState, target));
51+
}
52+
53+
@Execute
54+
@Permission("eternalcore.msgtoggle.other")
55+
@DescriptionDocs(description = "Switch receiving private messages for other player", arguments = "<player> <toggle>")
56+
void other(@Context CommandSender sender, @Arg Player target, @Arg PrivateChatState state) {
57+
UUID player = target.getUniqueId();
58+
this.privateChatStateService.setChatState(player, state)
59+
.thenAccept(ignored -> noticeOtherPlayer(sender, state, target));
60+
}
61+
62+
private void noticeOtherPlayer(CommandSender sender, PrivateChatState state, Player target) {
63+
this.noticePlayer(state, target.getUniqueId());
64+
if (sender.equals(target)) {
65+
return;
66+
}
67+
68+
this.noticeService.create()
69+
.sender(sender)
70+
.notice(translation -> state == PrivateChatState.DISABLE
71+
? translation.privateChat().otherMessagesDisabled()
72+
: translation.privateChat().otherMessagesEnabled()
73+
)
74+
.placeholder("{PLAYER}", target.getName())
75+
.send();
76+
}
77+
78+
private void noticePlayer(PrivateChatState state, UUID player) {
79+
this.noticeService.create()
80+
.player(player)
81+
.notice(translation -> state == PrivateChatState.ENABLE
82+
? translation.privateChat().selfMessagesEnabled()
83+
: translation.privateChat().selfMessagesDisabled()
84+
)
85+
.send();
86+
}
87+
88+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.eternalcode.core.feature.privatechat.toggle;
2+
3+
4+
import java.util.UUID;
5+
import java.util.concurrent.CompletableFuture;
6+
7+
interface PrivateChatStateRepository {
8+
9+
CompletableFuture<PrivateChatState> getPrivateChatState(UUID uuid);
10+
11+
CompletableFuture<Void> setPrivateChatState(UUID uuid, PrivateChatState toggledOff);
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.eternalcode.core.feature.privatechat.toggle;
2+
3+
import com.eternalcode.commons.scheduler.Scheduler;
4+
import com.eternalcode.core.database.DatabaseManager;
5+
import com.eternalcode.core.database.wrapper.AbstractRepositoryOrmLite;
6+
import com.eternalcode.core.injector.annotations.Inject;
7+
import com.eternalcode.core.injector.annotations.component.Repository;
8+
import com.j256.ormlite.table.TableUtils;
9+
import java.sql.SQLException;
10+
import java.util.UUID;
11+
import java.util.concurrent.CompletableFuture;
12+
13+
@Repository
14+
class PrivateChatStateRepositoryOrmLite extends AbstractRepositoryOrmLite implements PrivateChatStateRepository {
15+
16+
@Inject
17+
private PrivateChatStateRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) throws SQLException {
18+
super(databaseManager, scheduler);
19+
TableUtils.createTableIfNotExists(databaseManager.connectionSource(), PrivateChatStateWrapper.class);
20+
}
21+
22+
@Override
23+
public CompletableFuture<PrivateChatState> getPrivateChatState(UUID uuid) {
24+
return this.selectSafe(PrivateChatStateWrapper.class, uuid)
25+
.thenApply(
26+
optional -> optional.map(PrivateChatStateWrapper::isEnabled).orElse(PrivateChatState.ENABLE)
27+
).exceptionally(throwable -> PrivateChatState.ENABLE);
28+
}
29+
30+
@Override
31+
public CompletableFuture<Void> setPrivateChatState(UUID uuid, PrivateChatState state) {
32+
return this.save(PrivateChatStateWrapper.class, new PrivateChatStateWrapper(uuid, state))
33+
.thenApply(status -> null);
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.eternalcode.core.feature.privatechat.toggle;
2+
3+
import com.eternalcode.core.injector.annotations.Inject;
4+
import com.eternalcode.core.injector.annotations.component.Service;
5+
import java.util.UUID;
6+
import java.util.concurrent.CompletableFuture;
7+
import java.util.concurrent.ConcurrentHashMap;
8+
import java.util.concurrent.ConcurrentSkipListMap;
9+
10+
@Service
11+
class PrivateChatStateServiceImpl implements PrivateChatStateService {
12+
13+
private final PrivateChatStateRepository msgToggleRepository;
14+
private final ConcurrentHashMap<UUID, PrivateChatState> cachedToggleStates;
15+
16+
@Inject
17+
PrivateChatStateServiceImpl(PrivateChatStateRepository msgToggleRepository) {
18+
this.cachedToggleStates = new ConcurrentHashMap<>();
19+
this.msgToggleRepository = msgToggleRepository;
20+
21+
}
22+
23+
24+
@Override
25+
public CompletableFuture<PrivateChatState> getChatState(UUID playerUniqueId) {
26+
if (this.cachedToggleStates.containsKey(playerUniqueId)) {
27+
return CompletableFuture.completedFuture(this.cachedToggleStates.get(playerUniqueId));
28+
}
29+
30+
return this.msgToggleRepository.getPrivateChatState(playerUniqueId);
31+
}
32+
33+
@Override
34+
public CompletableFuture<Void> setChatState(UUID playerUniqueId, PrivateChatState state) {
35+
this.cachedToggleStates.put(playerUniqueId, state);
36+
37+
return this.msgToggleRepository.setPrivateChatState(playerUniqueId, state)
38+
.exceptionally(throwable -> {
39+
this.cachedToggleStates.remove(playerUniqueId);
40+
return null;
41+
});
42+
}
43+
44+
@Override
45+
public CompletableFuture<PrivateChatState> toggleChatState(UUID playerUniqueId) {
46+
return this.getChatState(playerUniqueId).thenCompose(state -> {
47+
PrivateChatState newState = state.invert();
48+
return this.setChatState(playerUniqueId, newState)
49+
.thenApply(aVoid -> newState);
50+
});
51+
}
52+
}

0 commit comments

Comments
 (0)