All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.freya022.botcommands.api.utils.RichTextFinder Maven / Gradle / Ivy

Go to download

A Kotlin-first (and Java) framework that makes creating Discord bots a piece of cake, using the JDA library.

There is a newer version: 3.0.0-alpha.18
Show newest version
package io.github.freya022.botcommands.api.utils;

import com.vdurmont.emoji.EmojiParser;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Utility class to search for rich text.
 * 
Rich text include: *
    *
  • Users
  • *
  • Text channels
  • *
  • Emotes
  • *
  • Roles
  • *
  • Unicode/shortcode emojis
  • *
  • {@code @here} and {@code @everyone} mentions
  • *
  • URLs
  • *
* * This class takes your input and tokenises it as it finds what you're asking it to find. *

* You can then take the output using {@link #getResults()} or consume it directly using {@link #processResults(RichTextConsumer)}. */ public class RichTextFinder extends EmojiParser { private static final Pattern urlPattern = Pattern.compile("https?://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]"); private static final Pattern EMPTY_PATTERN = Pattern.compile(""); private final String input; private final Matcher matcher; private final Map normalMentionMap = new TreeMap<>(); private final Map addedStrs = new TreeMap<>(); /** * Parses the input for what you're asking * * @param input The input to parse * @param getIMentionable Whether to take Users/Channels/Emotes/Roles * @param getGlobalMentions Whether to take {@code @here} and {@code @everyone} mentions * @param getEmojis Whether to take Unicode/shortcode emojis * @param getUrls Whether to take URLs */ public RichTextFinder(String input, boolean getIMentionable, boolean getGlobalMentions, boolean getEmojis, boolean getUrls) { this.input = input.replace("\uFE0F", ""); this.matcher = EMPTY_PATTERN.matcher(this.input); if (getIMentionable) { findAllMentions(RichTextType.USER, RichTextType.USER.getPattern()); findAllMentions(RichTextType.CHANNEL, RichTextType.CHANNEL.getPattern()); findAllMentions(RichTextType.EMOJI, RichTextType.EMOJI.getPattern()); findAllMentions(RichTextType.ROLE, RichTextType.ROLE.getPattern()); } if (getGlobalMentions) { findAllMentions(RichTextType.HERE, RichTextType.HERE.getPattern()); findAllMentions(RichTextType.EVERYONE, RichTextType.EVERYONE.getPattern()); } if (getEmojis) { resolveEmojis(); } if (getUrls) { findAllMentions(RichTextType.URL, urlPattern); } if (!addedStrs.isEmpty()) { Iterator it = addedStrs.values().iterator(); String next = it.next(); int startIndex = 0; int endIndex = input.indexOf(next, startIndex); final String startSubstring = this.input.substring(startIndex, endIndex).trim(); if (!startSubstring.isEmpty()) { normalMentionMap.put(startIndex, new RichText(startSubstring, RichTextType.TEXT)); } while (it.hasNext()) { startIndex = endIndex + next.length(); next = it.next(); endIndex = input.indexOf(next, startIndex); final String middleSubstring = this.input.substring(startIndex, endIndex).trim(); if (!middleSubstring.isEmpty()) { normalMentionMap.put(startIndex, new RichText(middleSubstring, RichTextType.TEXT)); } } startIndex = endIndex + next.length(); final String endSubstring = this.input.substring(startIndex).trim(); if (!endSubstring.isEmpty()) { normalMentionMap.put(startIndex, new RichText(endSubstring, RichTextType.TEXT)); } addedStrs.clear(); } else { normalMentionMap.put(0, new RichText(this.input, RichTextType.TEXT)); } } /** * @return The tokens parsed as rich text */ public List getResults() { return List.copyOf(normalMentionMap.values()); } private void resolveEmojis() { //Find emoji aliases final int inputLength = input.length(); for (int last = 0; last < inputLength; last++) { AliasCandidate alias = getAliasAt(input, last); if (alias != null) { last = alias.endIndex; final String substring; if (alias.fitzpatrick != null) { substring = alias.emoji.getUnicode() + alias.fitzpatrick.unicode; } else { substring = alias.emoji.getUnicode(); } final int beginIndex = last; final boolean isInsideCustomEmote = normalMentionMap.values().stream().filter(r -> r.type == RichTextType.EMOJI).anyMatch(r -> { final List aliases = alias.emoji.getAliases(); for (String aliasItem : aliases) { final boolean customEmoteHasEmoji = r.substring.startsWith(':' + aliasItem + ':', 1); if (customEmoteHasEmoji) { return true; } } return false; }); if (!isInsideCustomEmote) { // System.out.println("added emoji " + substring); normalMentionMap.put(beginIndex, new RichText(substring, RichTextType.UNICODE_EMOTE)); addedStrs.put(beginIndex, input.substring(alias.startIndex, alias.endIndex + 1)); } } } //Find unicode emojis char[] inputCharArray = input.toCharArray(); UnicodeCandidate next; for (int i = 0; (next = getNextUnicodeCandidate(inputCharArray, i)) != null; i = next.getFitzpatrickEndIndex()) { if (next.hasFitzpatrick()) { normalMentionMap.put(next.getEmojiStartIndex(), new RichText(next.getEmoji().getUnicode(next.getFitzpatrick()), RichTextType.UNICODE_EMOTE)); addedStrs.put(next.getEmojiStartIndex(), next.getEmoji().getUnicode(next.getFitzpatrick())); } else { normalMentionMap.put(next.getEmojiStartIndex(), new RichText(next.getEmoji().getUnicode(), RichTextType.UNICODE_EMOTE)); addedStrs.put(next.getEmojiStartIndex(), next.getEmoji().getUnicode()); } } } private void findAllMentions(RichTextType type, Pattern pattern) { matcher.usePattern(pattern); matcher.reset(); while (matcher.find()) { final String group = matcher.group(); normalMentionMap.put(matcher.start(), new RichText(group, type)); addedStrs.put(matcher.start(), group); } } /** * Processes each rich text token * @param consumer The consumer accepting a substring and a rich text type */ public void processResults(RichTextConsumer consumer) { for (RichText richText : normalMentionMap.values()) { consumer.consume(richText.substring, richText.type); } } public Map getNormalMentionMap() { return normalMentionMap; } public static class RichText { private final String substring; private final RichTextType type; RichText(String substring, RichTextType type) { this.substring = substring; this.type = type; } public String getSubstring() { return substring; } public RichTextType getType() { return type; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy