Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-870 Add /msgtoggle command #896

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open

GH-870 Add /msgtoggle command #896

wants to merge 18 commits into from

Conversation

CitralFlo
Copy link
Member

To clarify:
ON - true - means that the player has turned on msgToggle and has blocked getting private messages
OFF - false - means that the player has turned off msgToggle and has allowed getting private messages

@CitralFlo CitralFlo linked an issue Jan 22, 2025 that may be closed by this pull request
Copy link
Contributor

coderabbitai bot commented Jan 22, 2025

Walkthrough

The pull request introduces a new /msgtoggle command for managing private message settings in the EternalCore plugin. This command allows players to enable or disable receiving private messages, enhancing user control over chat interactions. The implementation includes new service classes, repositories, and updates to translations in both English and Polish.

A comprehensive system for tracking and managing private message toggle states is established, allowing players to check and modify their settings or those of others. The functionality is designed to operate asynchronously and persistently, storing toggle states in a database to ensure consistent behavior across server sessions.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4709133 and 450813c.

📒 Files selected for processing (1)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleServiceImpl.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleServiceImpl.java

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (6)
eternalcore-api/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggleService.java (1)

6-12: Add documentation to explain the interface's purpose.

Adding some simple comments would help other developers understand what this interface does and how to use it.

 public interface MsgToggleService {
+    /**
+     * Checks if a player has message toggle enabled
+     * @param uuid Player's UUID
+     * @return Future containing true if messages are toggled off
+     */
     CompletableFuture<Boolean> hasMsgToggled(UUID uuid);

+    /**
+     * Updates a player's message toggle state
+     * @param uuid Player's UUID
+     * @param toggle True to enable message blocking, false to disable
+     */
     void toggleMsg(UUID uuid, boolean toggle);
 }
eternalcore-core/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggleRepository.java (1)

10-10: Make method name clearer.

The name setToggledOff might be confusing when used with false. Consider renaming it to setToggleState to better reflect its purpose.

-    CompletableFuture<Void> setToggledOff(UUID uuid, boolean toggledOff);
+    CompletableFuture<Void> setToggleState(UUID uuid, boolean enabled);
eternalcore-core/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggleServiceImpl.java (1)

26-29: Consider removing @Blocking annotation

The @Blocking annotation might be misleading here since the repository operation could be asynchronous.

eternalcore-core/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggleRepositoryOrmLite.java (1)

31-34: Simplify CompletableFuture chain

The thenApply(status -> null) can be replaced with thenRun(() -> {}) for better readability.

-    public CompletableFuture<Void> setToggledOff(UUID uuid, boolean toggledOff) {
-        return this.save(MsgToggleWrapper.class, new MsgToggleWrapper(uuid, toggledOff))
-            .thenApply(status -> null);
-    }
+    public CompletableFuture<Void> setToggledOff(UUID uuid, boolean toggledOff) {
+        return this.save(MsgToggleWrapper.class, new MsgToggleWrapper(uuid, toggledOff))
+            .thenRun(() -> {});
+    }
eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/PrivateChatServiceImpl.java (1)

62-78: Improve async operation flow

The nested async operations can be flattened using CompletableFuture's composition methods for better readability.

-        this.msgToggleService.hasMsgToggled(uniqueId).thenAccept(hasMsgToggled -> {
-            if (hasMsgToggled) {
-                this.noticeService.player(sender.getUniqueId(), translation -> translation.privateChat().msgToggledOff());
-
-                return;
-            }
-
-            this.ignoreService.isIgnored(uniqueId, sender.getUniqueId()).thenAccept(isIgnored -> {
-                if (!isIgnored) {
-                    this.replies.put(uniqueId, sender.getUniqueId());
-                    this.replies.put(sender.getUniqueId(), uniqueId);
-                }
-
-                PrivateChatEvent event = new PrivateChatEvent(sender.getUniqueId(), uniqueId, message);
-                this.eventCaller.callEvent(event);
-                this.presenter.onPrivate(new PrivateMessage(sender, target, event.getContent(), this.socialSpy, isIgnored));
-            });
-        });
+        this.msgToggleService.hasMsgToggled(uniqueId)
+            .thenCompose(hasMsgToggled -> {
+                if (hasMsgToggled) {
+                    this.noticeService.player(sender.getUniqueId(), translation -> translation.privateChat().msgToggledOff());
+                    return CompletableFuture.completedFuture(null);
+                }
+                return this.ignoreService.isIgnored(uniqueId, sender.getUniqueId())
+                    .thenAccept(isIgnored -> {
+                        if (!isIgnored) {
+                            this.replies.put(uniqueId, sender.getUniqueId());
+                            this.replies.put(sender.getUniqueId(), uniqueId);
+                        }
+                        PrivateChatEvent event = new PrivateChatEvent(sender.getUniqueId(), uniqueId, message);
+                        this.eventCaller.callEvent(event);
+                        this.presenter.onPrivate(new PrivateMessage(sender, target, event.getContent(), this.socialSpy, isIgnored));
+                    });
+            });
eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/ENTranslation.java (1)

499-507: Consider standardizing color usage across messages.

While the messages are clear, the color usage could be more consistent:

  • Some messages use <red>disabled while others use <green>enabled
  • The player name highlighting varies between messages

Consider standardizing to:

-        public Notice msgToggledOff = Notice.chat("<red>► <dark_red>This player has disabled private messages!");
+        public Notice msgToggledOff = Notice.chat("<red>► <white>This player has <red>disabled</red> private messages!");

-        public Notice msgToggledSelf = Notice.chat("<green>► <white>Private messages have been <red>disabled<white>!");
+        public Notice msgToggledSelf = Notice.chat("<green>► <white>Private messages have been <red>disabled</red>!");

-        public Notice msgUntoggleSelf = Notice.chat("<green>► <white>Private messages have been <green>enabled<white>!");
+        public Notice msgUntoggleSelf = Notice.chat("<green>► <white>Private messages have been <green>enabled</green>!");
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 046c0df and aa1ff47.

📒 Files selected for processing (12)
  • README.md (1 hunks)
  • eternalcore-api/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggle.java (1 hunks)
  • eternalcore-api/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggleService.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggleCommand.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggleRepository.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggleRepositoryOrmLite.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggleServiceImpl.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggleWrapper.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/PrivateChatServiceImpl.java (4 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/translation/Translation.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/ENTranslation.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/PLTranslation.java (1 hunks)
🔇 Additional comments (7)
eternalcore-core/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggleServiceImpl.java (1)

20-23: Implementation looks good!

Clean and straightforward implementation of the message toggle service.

eternalcore-core/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggleRepositoryOrmLite.java (1)

23-28: Verify default value choice

The method returns true by default, which means messages are blocked by default. Is this the intended behavior?

eternalcore-core/src/main/java/com/eternalcode/core/feature/msgtoggle/MsgToggleCommand.java (1)

14-16: Well-structured command implementation!

Clear command descriptions and good separation between self and other-player operations.

Also applies to: 32-34, 47-48, 57-59, 69-71

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

41-42: Clean integration of MsgToggleService!

The message toggle feature is well integrated with the existing private chat system.

Also applies to: 48-48

README.md (1)

43-43: LGTM! Documentation updated appropriately.

The new /msgtoggle command is properly documented in the features list.

eternalcore-core/src/main/java/com/eternalcode/core/translation/Translation.java (1)

263-267: LGTM! Well-structured interface additions.

The new message toggle methods follow a consistent naming pattern and clearly indicate their purpose.

eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/PLTranslation.java (1)

508-515: LGTM! Well-structured Polish translations.

The Polish translations are properly localized while maintaining consistency with the English version.

@CitralFlo CitralFlo changed the title Add /msgtoggle command GH-870 Add /msgtoggle command Jan 22, 2025
@vLuckyyy vLuckyyy requested review from imDMK and removed request for VerniQ and imDMK January 23, 2025 18:20
Copy link
Member

@Jakubk15 Jakubk15 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To co napisał @imDMK ale imo msgToggle ogólnie brzmi dziwnie. Jako nazwa obiektu spoko - ale wewnętrznie powinniśmy tworzyć spójne nazewnictwo typu MsgEnabledState, a nie MsgToggleState. Wtedy bez czytania komentarzy w kodzie wiadomo o co chodzi.

Można także dodać shortcuty /msg enable /msg disable dla spójności tylko trzeba tam łapać te argumenty bo nie chcemy mieć sytuacji kiedy wbiją gracze z nazwami enable i disable 🤡

Copy link
Member

@Rollczi Rollczi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To tak, MSG jest ok słowem w kontekście mc i jak mamy go używać to trzeba zrobić rename "privatemessage" na msg imo jednak tak z praktycznego punktu widzenia bo mieszamy trochę teraz te rzeczy. Ewentualnie możemy używać "tell" czy coś no ale to jakaś dyskusja na dalszy temat

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🧹 Nitpick comments (9)
eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleRepository.java (1)

11-11: Consider renaming the parameter for clarity

The parameter name toggledOff might be confusing since it can be either ON or OFF. Consider using just state or toggleState instead.

-    CompletableFuture<Void> setPrivateChatToggle(UUID uuid, PrivateChatToggleState toggledOff);
+    CompletableFuture<Void> setPrivateChatToggle(UUID uuid, PrivateChatToggleState state);
eternalcore-api/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggle.java (2)

10-12: Consider removing unused constructor

The empty constructor doesn't initialize the fields. If all fields are required, consider removing it.


14-17: Make parameter name match field name

For consistency, rename the parameter to match the field name.

-    public PrivateChatToggle(UUID uuid, PrivateChatToggleState toggle) {
+    public PrivateChatToggle(UUID uuid, PrivateChatToggleState state) {
         this.uuid = uuid;
-        this.state = toggle;
+        this.state = state;
     }
eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleServiceImpl.java (1)

18-18: Remove extra blank lines

There are unnecessary blank lines that can be removed.

Also applies to: 29-29

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

63-79: Consider combining async operations.

The nested async operations could be flattened using thenCompose for better readability and error handling.

-        this.privateChatToggleService.getPrivateChatToggleState(uniqueId).thenAccept(privateChatToggleState -> {
-            if (privateChatToggleState.equals(PrivateChatToggleState.ON)) {
-                this.noticeService.player(sender.getUniqueId(), translation -> translation.privateChat().receiverDisabledMessages());
-
-                return;
-            }
-
-            this.ignoreService.isIgnored(uniqueId, sender.getUniqueId()).thenAccept(isIgnored -> {
+        this.privateChatToggleService.getPrivateChatToggleState(uniqueId)
+            .thenCompose(privateChatToggleState -> {
+                if (privateChatToggleState.equals(PrivateChatToggleState.ON)) {
+                    this.noticeService.player(sender.getUniqueId(), 
+                        translation -> translation.privateChat().receiverDisabledMessages());
+                    return CompletableFuture.completedFuture(null);
+                }
+                return this.ignoreService.isIgnored(uniqueId, sender.getUniqueId())
+                    .thenAccept(isIgnored -> {
                 if (!isIgnored) {
                     this.replies.put(uniqueId, sender.getUniqueId());
                     this.replies.put(sender.getUniqueId(), uniqueId);
                 }

                 PrivateChatEvent event = new PrivateChatEvent(sender.getUniqueId(), uniqueId, message);
                 this.eventCaller.callEvent(event);
                 this.presenter.onPrivate(new PrivateMessage(sender, target, event.getContent(), this.socialSpy, isIgnored));
-            });
-        });
+            });
+        })
+        .exceptionally(throwable -> {
+            this.noticeService.player(sender.getUniqueId(), 
+                translation -> translation.general().error());
+            return null;
+        });
eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleRepositoryOrmLite.java (2)

31-34: Simplify the CompletableFuture chain.

The thenApply(status -> null) can be replaced with a simpler method.

-        return this.save(PrivateChatToggleWrapper.class, new PrivateChatToggleWrapper(uuid, toggledOff))
-            .thenApply(status -> null);
+        return this.save(PrivateChatToggleWrapper.class, new PrivateChatToggleWrapper(uuid, toggledOff))
+            .thenRun(() -> {});

30-34: Add documentation for the return value.

The method returns null via thenApply(status -> null). This should be documented or reconsidered.

+    /**
+     * Sets the private chat toggle state for a player.
+     * @return A CompletableFuture that completes when the save operation is done.
+     */
     @Override
     public CompletableFuture<Void> setPrivateChatToggle(UUID uuid, PrivateChatToggleState toggledOff) {
         return this.save(PrivateChatToggleWrapper.class, new PrivateChatToggleWrapper(uuid, toggledOff))
             .thenApply(status -> null);
     }
eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleCommand.java (2)

116-123: Consider merging toggle methods to reduce duplication.

The toggleOn and toggleOff methods are very similar and could be combined.

-    private void toggleOn(UUID uniqueId) {
-        this.privateChatToggleService.togglePrivateChat(uniqueId, PrivateChatToggleState.ON);
-
-        this.noticeService.create()
-            .notice(translation -> translation.privateChat().selfMessagesDisabled())
-            .player(uniqueId)
-            .send();
-    }
-
-    private void toggleOff(UUID uniqueId) {
-        this.privateChatToggleService.togglePrivateChat(uniqueId, PrivateChatToggleState.OFF);
-
-        this.noticeService.create()
-            .notice(translation -> translation.privateChat().selfMessagesEnabled())
-            .player(uniqueId)
-            .send();
-    }
+    private void toggle(UUID uniqueId, PrivateChatToggleState state) {
+        this.privateChatToggleService.togglePrivateChat(uniqueId, state);
+
+        this.noticeService.create()
+            .notice(translation -> state == PrivateChatToggleState.ON 
+                ? translation.privateChat().selfMessagesDisabled()
+                : translation.privateChat().selfMessagesEnabled())
+            .player(uniqueId)
+            .send();
+    }

Also applies to: 125-132


116-132: Reduce code duplication in notification methods.

The toggleOn and toggleOff methods have similar notification logic.

Consider extracting the notification logic to a separate method:

+    private void sendToggleNotification(UUID uniqueId, boolean enabled) {
+        this.noticeService.create()
+            .notice(translation -> enabled 
+                ? translation.privateChat().selfMessagesEnabled()
+                : translation.privateChat().selfMessagesDisabled())
+            .player(uniqueId)
+            .send();
+    }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa1ff47 and 97d5914.

📒 Files selected for processing (13)
  • README.md (1 hunks)
  • eternalcore-api/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggle.java (1 hunks)
  • eternalcore-api/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleService.java (1 hunks)
  • eternalcore-api/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleState.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/PrivateChatServiceImpl.java (4 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleCommand.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleRepository.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleRepositoryOrmLite.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleServiceImpl.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleWrapper.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/translation/Translation.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/ENTranslation.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/PLTranslation.java (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • eternalcore-api/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleState.java
🚧 Files skipped from review as they are similar to previous changes (3)
  • eternalcore-core/src/main/java/com/eternalcode/core/translation/Translation.java
  • eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/PLTranslation.java
  • README.md
👮 Files not reviewed due to content moderation or server errors (4)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleWrapper.java
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleRepositoryOrmLite.java
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleCommand.java
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/PrivateChatServiceImpl.java
🔇 Additional comments (4)
eternalcore-api/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleService.java (1)

6-11: Nice and clean interface design!

The async methods look good and handle the toggle state well.

eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleCommand.java (2)

116-123: Inconsistent message notifications in toggle methods.

The toggleOn method shows "disabled" message while toggleOff shows "enabled" message. This seems counterintuitive and might confuse users.

Could you verify if this is the intended behavior? The message seems to be reversed from what the method names suggest.

Also applies to: 125-132


38-48: ⚠️ Potential issue

Fix inconsistent toggle logic.

The toggle logic is reversed. When state is OFF, you're calling toggleOn, and vice versa. This is counterintuitive.

-                if (toggleState.equals(PrivateChatToggleState.OFF)) {
+                if (toggleState.equals(PrivateChatToggleState.ON)) {
                     this.toggleOn(uniqueId);
                 }
                 else {
                     this.toggleOff(uniqueId);
                 }

Likely invalid or redundant comment.

eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/ENTranslation.java (1)

499-510: Nice work on the message formatting!

The new messages for the private messaging toggle feature are clear, consistent with the existing style, and effectively communicate the state changes to users.

Comment on lines +63 to +79
this.privateChatToggleService.getPrivateChatToggleState(uniqueId).thenAccept(privateChatToggleState -> {
if (privateChatToggleState.equals(PrivateChatToggleState.ON)) {
this.noticeService.player(sender.getUniqueId(), translation -> translation.privateChat().receiverDisabledMessages());

return;
}

PrivateChatEvent event = new PrivateChatEvent(sender.getUniqueId(), target.getUniqueId(), message);
this.eventCaller.callEvent(event);
this.presenter.onPrivate(new PrivateMessage(sender, target, event.getContent(), this.socialSpy, isIgnored));
this.ignoreService.isIgnored(uniqueId, sender.getUniqueId()).thenAccept(isIgnored -> {
if (!isIgnored) {
this.replies.put(uniqueId, sender.getUniqueId());
this.replies.put(sender.getUniqueId(), uniqueId);
}

PrivateChatEvent event = new PrivateChatEvent(sender.getUniqueId(), uniqueId, message);
this.eventCaller.callEvent(event);
this.presenter.onPrivate(new PrivateMessage(sender, target, event.getContent(), this.socialSpy, isIgnored));
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider handling CompletableFuture exceptions.

The async operations don't handle potential exceptions that could occur during database access.

         this.privateChatToggleService.getPrivateChatToggleState(uniqueId).thenAccept(privateChatToggleState -> {
             if (privateChatToggleState.equals(PrivateChatToggleState.ON)) {
                 this.noticeService.player(sender.getUniqueId(), translation -> translation.privateChat().receiverDisabledMessages());
 
                 return;
             }
 
             this.ignoreService.isIgnored(uniqueId, sender.getUniqueId()).thenAccept(isIgnored -> {
                 if (!isIgnored) {
                     this.replies.put(uniqueId, sender.getUniqueId());
                     this.replies.put(sender.getUniqueId(), uniqueId);
                 }
 
                 PrivateChatEvent event = new PrivateChatEvent(sender.getUniqueId(), uniqueId, message);
                 this.eventCaller.callEvent(event);
                 this.presenter.onPrivate(new PrivateMessage(sender, target, event.getContent(), this.socialSpy, isIgnored));
-            });
+            }).exceptionally(throwable -> {
+                this.noticeService.player(sender.getUniqueId(), translation -> translation.general().error());
+                return null;
+            });
-        });
+        }).exceptionally(throwable -> {
+            this.noticeService.player(sender.getUniqueId(), translation -> translation.general().error());
+            return null;
+        });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.privateChatToggleService.getPrivateChatToggleState(uniqueId).thenAccept(privateChatToggleState -> {
if (privateChatToggleState.equals(PrivateChatToggleState.ON)) {
this.noticeService.player(sender.getUniqueId(), translation -> translation.privateChat().receiverDisabledMessages());
return;
}
PrivateChatEvent event = new PrivateChatEvent(sender.getUniqueId(), target.getUniqueId(), message);
this.eventCaller.callEvent(event);
this.presenter.onPrivate(new PrivateMessage(sender, target, event.getContent(), this.socialSpy, isIgnored));
this.ignoreService.isIgnored(uniqueId, sender.getUniqueId()).thenAccept(isIgnored -> {
if (!isIgnored) {
this.replies.put(uniqueId, sender.getUniqueId());
this.replies.put(sender.getUniqueId(), uniqueId);
}
PrivateChatEvent event = new PrivateChatEvent(sender.getUniqueId(), uniqueId, message);
this.eventCaller.callEvent(event);
this.presenter.onPrivate(new PrivateMessage(sender, target, event.getContent(), this.socialSpy, isIgnored));
});
this.privateChatToggleService.getPrivateChatToggleState(uniqueId).thenAccept(privateChatToggleState -> {
if (privateChatToggleState.equals(PrivateChatToggleState.ON)) {
this.noticeService.player(sender.getUniqueId(), translation -> translation.privateChat().receiverDisabledMessages());
return;
}
this.ignoreService.isIgnored(uniqueId, sender.getUniqueId()).thenAccept(isIgnored -> {
if (!isIgnored) {
this.replies.put(uniqueId, sender.getUniqueId());
this.replies.put(sender.getUniqueId(), uniqueId);
}
PrivateChatEvent event = new PrivateChatEvent(sender.getUniqueId(), uniqueId, message);
this.eventCaller.callEvent(event);
this.presenter.onPrivate(new PrivateMessage(sender, target, event.getContent(), this.socialSpy, isIgnored));
}).exceptionally(throwable -> {
this.noticeService.player(sender.getUniqueId(), translation -> translation.general().error());
return null;
});
}).exceptionally(throwable -> {
this.noticeService.player(sender.getUniqueId(), translation -> translation.general().error());
return null;
});

🛠️ Refactor suggestion

Simplify nested async operations.

The nested async operations make the code hard to follow and maintain.

Consider using thenCompose to flatten the async operations:

-        this.privateChatToggleService.getPrivateChatToggleState(uniqueId).thenAccept(privateChatToggleState -> {
-            if (privateChatToggleState.equals(PrivateChatToggleState.ON)) {
-                this.noticeService.player(sender.getUniqueId(), translation -> translation.privateChat().receiverDisabledMessages());
-                return;
-            }
-            this.ignoreService.isIgnored(uniqueId, sender.getUniqueId()).thenAccept(isIgnored -> {
+        this.privateChatToggleService.getPrivateChatToggleState(uniqueId)
+            .thenCompose(privateChatToggleState -> {
+                if (privateChatToggleState.equals(PrivateChatToggleState.ON)) {
+                    this.noticeService.player(sender.getUniqueId(), 
+                        translation -> translation.privateChat().receiverDisabledMessages());
+                    return CompletableFuture.completedFuture(null);
+                }
+                return this.ignoreService.isIgnored(uniqueId, sender.getUniqueId())
+                    .thenAccept(isIgnored -> {

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +63 to +78
this.privateChatToggleService.getPrivateChatToggleState(uniqueId).thenAccept(privateChatToggleState -> {
if (privateChatToggleState.equals(PrivateChatToggleState.ON)) {
this.noticeService.player(sender.getUniqueId(), translation -> translation.privateChat().receiverDisabledMessages());

return;
}

PrivateChatEvent event = new PrivateChatEvent(sender.getUniqueId(), target.getUniqueId(), message);
this.eventCaller.callEvent(event);
this.presenter.onPrivate(new PrivateMessage(sender, target, event.getContent(), this.socialSpy, isIgnored));
this.ignoreService.isIgnored(uniqueId, sender.getUniqueId()).thenAccept(isIgnored -> {
if (!isIgnored) {
this.replies.put(uniqueId, sender.getUniqueId());
this.replies.put(sender.getUniqueId(), uniqueId);
}

PrivateChatEvent event = new PrivateChatEvent(sender.getUniqueId(), uniqueId, message);
this.eventCaller.callEvent(event);
this.presenter.onPrivate(new PrivateMessage(sender, target, event.getContent(), this.socialSpy, isIgnored));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trzeba jeszcze przemyśleć trochę to api serwisu - czy jest sens robić 2 osobne serwisy (dla toggle) i czy da się te rzeczy zrobić ładniej bo teraz robi sam się trochę śmietnik w PrivateChatService

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tbh I don't understand. Please elaborate

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleCommand.java (1)

36-49: ⚠️ Potential issue

Add error handling for the async operation.

The async operation could fail silently. Let's add proper error handling.

     if (state == null) {
         CompletableFuture<PrivateChatToggleState> privateChatToggleState = this.privateChatToggleService.getPrivateChatToggleState(context.getUniqueId());

         privateChatToggleState.thenAccept(toggleState -> {
             if (toggleState.equals(PrivateChatToggleState.OFF)) {
                 this.toggleOn(uniqueId);
             }
             else {
                 this.toggleOff(uniqueId);
             }
-        });
+        }).exceptionally(throwable -> {
+            this.noticeService.create()
+                .notice(translation -> translation.general().error())
+                .player(uniqueId)
+                .send();
+            return null;
+        });
🧹 Nitpick comments (3)
eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleServiceImpl.java (3)

23-29: Update cache on repository fetch

When fetching from the repository, the result should be cached to avoid repeated database calls.

     @Override
     public CompletableFuture<PrivateChatToggleState> getPrivateChatToggleState(UUID uuid) {
         if (this.cachedToggleStates.containsKey(uuid)) {
             return CompletableFuture.completedFuture(this.cachedToggleStates.get(uuid));
         }
 
-        return this.msgToggleRepository.getPrivateChatToggleState(uuid);
+        return this.msgToggleRepository.getPrivateChatToggleState(uuid)
+            .thenApply(state -> {
+                this.cachedToggleStates.put(uuid, state);
+                return state;
+            });
     }

32-35: Handle repository update failures

If the repository update fails, the cache and database could get out of sync. Consider handling the error case.

     @Override
     public void togglePrivateChat(UUID uuid, PrivateChatToggleState toggle) {
-        this.cachedToggleStates.put(uuid, toggle);
-        this.msgToggleRepository.setPrivateChatToggle(uuid, toggle);
+        this.msgToggleRepository.setPrivateChatToggle(uuid, toggle)
+            .thenAccept(ignored -> this.cachedToggleStates.put(uuid, toggle))
+            .exceptionally(throwable -> {
+                // Log error and remove from cache to force re-fetch
+                this.cachedToggleStates.remove(uuid);
+                return null;
+            });
     }

13-13: Add basic cache management

Consider adding simple cache management features like:

  • Maximum cache size limit
  • Cache entry expiration
  • Cache clear on player logout

This will help prevent memory issues while keeping the performance benefits.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 97d5914 and 4709133.

📒 Files selected for processing (7)
  • eternalcore-api/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggle.java (1 hunks)
  • eternalcore-api/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleService.java (1 hunks)
  • eternalcore-api/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleState.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleCommand.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleRepository.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleServiceImpl.java (1 hunks)
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleWrapper.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • eternalcore-api/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleState.java
  • eternalcore-api/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggle.java
  • eternalcore-api/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleService.java
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleRepository.java
  • eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleWrapper.java
🧰 Additional context used
📓 Learnings (2)
eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleServiceImpl.java (2)
Learnt from: CitralFlo
PR: EternalCodeTeam/EternalCore#896
File: eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleServiceImpl.java:24-27
Timestamp: 2025-01-28T21:35:47.750Z
Learning: In EternalCore, async operations using CompletableFuture should remain non-blocking. Avoid using .join() or similar blocking operations to maintain better performance and scalability.
Learnt from: CitralFlo
PR: EternalCodeTeam/EternalCore#896
File: eternalcore-api/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggle.java:10-11
Timestamp: 2025-01-28T21:35:04.888Z
Learning: Fields in classes used with ORM Lite repository must have package-private (default) access modifier, not private, to allow ORM Lite to access them properly.
eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleCommand.java (1)
Learnt from: CitralFlo
PR: EternalCodeTeam/EternalCore#896
File: eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleCommand.java:92-102
Timestamp: 2025-01-28T21:37:36.945Z
Learning: In the EternalCore plugin's private chat feature, PrivateChatToggleState.ON means message blocking is enabled (no messages will be received), while PrivateChatToggleState.OFF means messages are allowed.
🔇 Additional comments (4)
eternalcore-core/src/main/java/com/eternalcode/core/feature/privatechat/toggle/PrivateChatToggleCommand.java (4)

18-29: Nice command setup!

The command structure is clean with proper permissions and dependency injection.


76-99: Toggle logic looks good!

The notification handling correctly differentiates between self and other players.


101-124: Helper methods are well organized!

The toggle operations are nicely separated into clear, focused methods.


66-71: ⚠️ Potential issue

Add error handling here too.

Just like in the self-toggle case, we need error handling for the async operation.

         if (state == null) {
             CompletableFuture<PrivateChatToggleState> privateChatToggleState = this.privateChatToggleService.getPrivateChatToggleState(uniqueId);
-            privateChatToggleState.thenAccept(toggleState -> handleToggle(context, player, toggleState, uniqueId));
+            privateChatToggleState
+                .thenAccept(toggleState -> handleToggle(context, player, toggleState, uniqueId))
+                .exceptionally(throwable -> {
+                    this.noticeService.create()
+                        .notice(translation -> translation.general().error())
+                        .sender(context)
+                        .send();
+                    return null;
+                });
             return;
         }

Likely invalid or redundant comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add private message toggle.
5 participants