-2

The title might be a little confusing, here's what's happening. I've got this piece of code:

private List<String> aswear = Arrays.asList("anus", "arse", "arsehole", "ass", "ass-hat", "ass-jabber", "ass-pirate", "assbag"); // A list with all swears starting with a.

    String message = event.getMessage(); // When a player sends a message to the server, this is his message.

    boolean asSwear = false; // A boolean to check if his sentence has a double swear.

    for(String as : aswear) { // Loop through all the swears.

        if (asSwear == false) { // Check if there is already an a swear.

            if (message.contains(as)) { // If his message contains a swear

                event.setCancelled(true); // Remove the message from the server

                event.getBukkitPlayer().sendMessage(PredefinedMessages.PHOENIX_SWEARING_DETECTED.build()); // Send a message saying he sweared.

                asSwear = true; // Set the boolean to true because he sweared.
            }

        }
    }

My problem is that when a player writes "Bass" in his message it'll block, yet bass isn't a swear. It blocks because it contains 'ass' in the message. Does anybody have a fix to this issue?

ElieTGM
  • 1
  • 1
  • 4

7 Answers7

3

use regex check instead of String.contains. Then you can match word-boundary using \b

Kent
  • 189,393
  • 32
  • 233
  • 301
  • It may be useful to the OP if you posted an example? I may add code later today if I have time. – RudolphEst Jan 06 '17 at 10:47
  • @RudolphEst I think two key words is enough for OP, `regex` and `\b` He just needs to go in this direction. I think he doesn't want to copy and paste working codes. – Kent Jan 06 '17 at 11:43
1

Use message.split("\\b") to get an array of all "words" in the message. For each word, check if your blacklist contains that word:

String[] msgWords = message.split("\\b");
for (String word : msgWords) {
  if (aswear.contains(word.toLowerCase(Locale.US))) {
    // do whatever has to be done
    break;
  }
}

EDIT: Used \\b as word boundary regex, which really simplifies things (slightly stolen from Kent's answer).

Florian Albrecht
  • 2,266
  • 1
  • 20
  • 25
0

How about to define the array as " ass " with spaces around the words and use the same logic?

Wavemaster
  • 1,794
  • 16
  • 27
  • "ass is there." it wont report any match. – jack jay Jan 06 '17 at 10:03
  • Thank you so much! I didn't think of that. Yet what jack said is correct. It doesn't block ass if it starts with ass. I'll add if startsWith and if not indent the message by one. Thank you so much Wavemaster. – ElieTGM Jan 06 '17 at 10:04
  • dont handle each and every boundary when you have other ways to do things. Like split your message and then iterate over it and check matches , or use regrex. – jack jay Jan 06 '17 at 10:11
0

How about a reversing the logic to iterate over player message with space as splitter and then checking whether that word is in your swear collection? That will give control

Rizwan
  • 2,369
  • 22
  • 27
0

If you are using Java 8 you can use following code

String message = event.getMessage(); // When a player sends a message to the server, this is his message.
if (aswear.stream().anyMatch(x -> x.equalsIgnoreCase(message.trim()))) {
    event.setCancelled(true);
    event.getBukkitPlayer().sendMessage(PredefinedMessages.PHOENIX_SWEARING_DETECTED.build());
}
Dmitry Gorkovets
  • 2,208
  • 1
  • 10
  • 19
0

What you could do, would be to split the player message after whitespaces, and then check all words in the message against the list of swears. Then if the message words are identical, or however you design the likeness percentage, then you block the word,e.g. replace it with something else.

Of course this works only for languages where the words in a sentence are delimited by whitespaces.

0

Split your message on words.

String[] words = message.split("\\b");

Then check if any of the words are in the banned words list.

boolean badWord = false;
for(String word: words){

    if(aswear.contains(word.toLowerCase())){
        badWord = true;
        break;
    }

}
matt
  • 10,892
  • 3
  • 22
  • 34
  • Seems to be quite identical to my answer... Although I did not use \\b as splitting regex (now changed). But you should always provide a locale for `toLowerCase`. – Florian Albrecht Jan 06 '17 at 10:26
  • Yes you updated your answer, you also left out the check to indicate you found a bad word, so either at the end they all look fine, or they all look bad. Incidentally I had started mine before you had finished. – matt Jan 06 '17 at 10:30
  • My answer included a "break" at any time. Setting a boolean and changing event states are "what has to be done", of course... as it is unclear if the OP really needs that boolean flag (it seems to be only there **instead** of a break in their loop). – Florian Albrecht Jan 06 '17 at 10:33
  • I don't really get your point. I was explaining the difference. – matt Jan 06 '17 at 10:36
  • I tried to make clear that there is no functional difference (and has never been), only the \\b which I added... but it is not really important nontheless, right. – Florian Albrecht Jan 06 '17 at 10:49