3 | * Copyright (c) 2021 under BSD 2, Ferrariic, Seltzer Bro, Cyborger1
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright notice, this
10 | * list of conditions and the following disclaimer.
11 | *
12 | * 2. Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 | package com.botdetector.model;
28 |
29 | import lombok.Value;
30 |
31 | /**
32 | * A string wrapper that makes .equals a caseInsensitive match
33 | *
34 | * a collection that wraps a String mapping in CaseInsensitiveStrings will still accept a String but will now
35 | * return a caseInsensitive match rather than a caseSensitive one
36 | *
37 | */
38 | @Value
39 | public class CaseInsensitiveString
40 | {
41 | String str;
42 |
43 | public static CaseInsensitiveString wrap(String str)
44 | {
45 | return new CaseInsensitiveString(str);
46 | }
47 |
48 | @Override
49 | public boolean equals(Object o)
50 | {
51 | if (this == o)
52 | {
53 | return true;
54 | }
55 |
56 | if (o == null)
57 | {
58 | return false;
59 | }
60 |
61 | if (o.getClass() == getClass())
62 | {
63 | // Is another CaseInsensitiveString
64 | CaseInsensitiveString that = (CaseInsensitiveString) o;
65 | return (str != null) ? str.equalsIgnoreCase(that.str) : that.str == null;
66 | }
67 |
68 | if (o.getClass() == String.class)
69 | {
70 | // Is just a regular String
71 | String that = (String) o;
72 | return that.equalsIgnoreCase(str);
73 | }
74 |
75 | return false;
76 | }
77 |
78 | @Override
79 | public int hashCode()
80 | {
81 | return (str != null) ? str.toUpperCase().hashCode() : 0;
82 | }
83 |
84 | @Override
85 | public String toString()
86 | {
87 | return str;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/com/botdetector/model/FeedbackPredictionLabel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021, Ferrariic, Seltzer Bro, Cyborger1
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | *
11 | * 2. Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | package com.botdetector.model;
27 |
28 | import java.util.Objects;
29 | import lombok.Value;
30 | import org.apache.commons.text.WordUtils;
31 |
32 | @Value
33 | public class FeedbackPredictionLabel
34 | {
35 | String label;
36 | String normalizedLabel;
37 | FeedbackValue feedbackValue;
38 | Double labelConfidence;
39 |
40 | public FeedbackPredictionLabel(String label, Double labelConfidence, FeedbackValue feedbackValue)
41 | {
42 | this.label = label;
43 | this.normalizedLabel = normalizeLabel(label);
44 | this.labelConfidence = labelConfidence;
45 | this.feedbackValue = feedbackValue;
46 | }
47 |
48 | @Override
49 | public boolean equals(Object o)
50 | {
51 | if (this == o)
52 | {
53 | return true;
54 | }
55 |
56 | if (o instanceof FeedbackPredictionLabel)
57 | {
58 | FeedbackPredictionLabel that = (FeedbackPredictionLabel) o;
59 | return Objects.equals(label, that.label)
60 | && Objects.equals(labelConfidence, that.labelConfidence)
61 | && Objects.equals(feedbackValue, that.feedbackValue);
62 | }
63 |
64 | return false;
65 | }
66 |
67 | @Override
68 | public int hashCode()
69 | {
70 | return (label != null ? label.hashCode() : 0)
71 | + (labelConfidence != null ? labelConfidence.hashCode() : 0)
72 | + (feedbackValue != null ? feedbackValue.hashCode() : 0);
73 | }
74 |
75 | @Override
76 | public String toString()
77 | {
78 | return normalizedLabel;
79 | }
80 |
81 | /**
82 | * Normalizes the given prediction label by separating word
83 | * with spaces and making each word capitalized.
84 | * @param label The label to normalize.
85 | * @return The normalized label.
86 | */
87 | public static String normalizeLabel(String label)
88 | {
89 | if (label == null)
90 | {
91 | return null;
92 | }
93 |
94 | return WordUtils.capitalize(label.replace('_', ' ').trim(), ' ');
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/com/botdetector/model/FeedbackValue.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021, Ferrariic, Seltzer Bro, Cyborger1
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | *
11 | * 2. Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | package com.botdetector.model;
27 |
28 | import lombok.Getter;
29 | import lombok.RequiredArgsConstructor;
30 |
31 | @Getter
32 | @RequiredArgsConstructor
33 | public enum FeedbackValue
34 | {
35 | POSITIVE(1),
36 | NEGATIVE(-1),
37 | NEUTRAL(0)
38 | ;
39 |
40 | private final int apiValue;
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/botdetector/model/PlayerSighting.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021, Ferrariic, Seltzer Bro, Cyborger1
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | *
11 | * 2. Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | package com.botdetector.model;
27 |
28 | import com.google.gson.annotations.SerializedName;
29 | import java.time.Instant;
30 | import java.util.Map;
31 | import lombok.Builder;
32 | import lombok.Value;
33 | import net.runelite.api.kit.KitType;
34 |
35 | @Value
36 | @Builder
37 | public class PlayerSighting
38 | {
39 | @SerializedName("reported")
40 | String playerName;
41 |
42 | @SerializedName("region_id")
43 | int regionID;
44 |
45 | @SerializedName("x_coord")
46 | int worldX;
47 |
48 | @SerializedName("y_coord")
49 | int worldY;
50 |
51 | @SerializedName("z_coord")
52 | int plane;
53 |
54 | @SerializedName("equipment")
55 | Map equipment;
56 |
57 | @SerializedName("equipment_ge_value")
58 | long equipmentGEValue;
59 |
60 | @SerializedName("world_number")
61 | int worldNumber;
62 |
63 | @SerializedName("on_members_world")
64 | boolean inMembersWorld;
65 |
66 | @SerializedName("on_pvp_world")
67 | boolean inPVPWorld;
68 |
69 | @SerializedName("ts")
70 | Instant timestamp;
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/com/botdetector/model/PlayerStats.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021, Ferrariic, Seltzer Bro, Cyborger1
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | *
11 | * 2. Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | package com.botdetector.model;
27 |
28 | import lombok.Builder;
29 | import lombok.Value;
30 |
31 | @Value
32 | @Builder
33 | public class PlayerStats
34 | {
35 | long namesUploaded;
36 | long confirmedBans;
37 | long possibleBans;
38 | long incorrectFlags;
39 | long feedbackSent;
40 |
41 | /**
42 | * The accuracy represents {@link #confirmedBans} divided by
43 | * the sum of {@link #confirmedBans} and {@link #incorrectFlags}.
44 | */
45 | public double getAccuracy()
46 | {
47 | long divisor = incorrectFlags + confirmedBans;
48 | return divisor > 0 ? confirmedBans / (double)divisor : 0;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/botdetector/model/PlayerStatsType.java:
--------------------------------------------------------------------------------
1 | package com.botdetector.model;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 | import lombok.Getter;
5 | import lombok.RequiredArgsConstructor;
6 | import lombok.experimental.Accessors;
7 |
8 | @Getter
9 | @RequiredArgsConstructor
10 | public enum PlayerStatsType
11 | {
12 | @SerializedName("manual")
13 | MANUAL("Manual", "Manual uploading statistics, uploads from manually flagging a player as a bot.", true),
14 | @SerializedName("passive")
15 | PASSIVE("Auto", "Passive uploading statistics, uploads from simply seeing other players in-game.", false),
16 | @SerializedName("total")
17 | TOTAL("Total", "Total uploading statistics, both passive and manual.", false)
18 | ;
19 |
20 | private final String shorthand;
21 | private final String description;
22 | @Accessors(fluent = true)
23 | private final boolean canDisplayAccuracy;
24 |
25 | @Override
26 | public String toString()
27 | {
28 | return shorthand;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/botdetector/model/Prediction.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021, Ferrariic, Seltzer Bro, Cyborger1
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | *
11 | * 2. Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | package com.botdetector.model;
27 |
28 | import com.google.gson.annotations.SerializedName;
29 | import java.util.Map;
30 | import lombok.Value;
31 | import lombok.Builder;
32 |
33 | @Value
34 | @Builder
35 | public class Prediction
36 | {
37 | @SerializedName("player_id")
38 | long playerId;
39 | @SerializedName("player_name")
40 | String playerName;
41 | @SerializedName("prediction_label")
42 | String predictionLabel;
43 | @SerializedName("prediction_confidence")
44 | Double confidence;
45 | @SerializedName("predictions_breakdown")
46 | Map predictionBreakdown;
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/botdetector/model/StatsCommandDetailLevel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021, Ferrariic, Seltzer Bro, Cyborger1
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | *
11 | * 2. Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | package com.botdetector.model;
27 |
28 | import lombok.Getter;
29 | import lombok.RequiredArgsConstructor;
30 |
31 | @Getter
32 | @RequiredArgsConstructor
33 | public enum StatsCommandDetailLevel
34 | {
35 | OFF("Disabled"),
36 | CONFIRMED_ONLY("Confirmed Bans"),
37 | DETAILED("Detailed Stats")
38 | ;
39 |
40 | private final String name;
41 |
42 | @Override
43 | public String toString()
44 | {
45 | return name;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/botdetector/ui/Icons.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021, Ferrariic, Seltzer Bro, Cyborger1
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | *
11 | * 2. Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | package com.botdetector.ui;
27 |
28 | import java.util.Objects;
29 | import javax.swing.ImageIcon;
30 | import net.runelite.client.util.ImageUtil;
31 |
32 | public class Icons
33 | {
34 | private static final Class> PLUGIN_CLASS = BotDetectorPanel.class;
35 |
36 | public static final ImageIcon GITHUB_ICON = new ImageIcon(ImageUtil.loadImageResource(PLUGIN_CLASS, "github.png"));
37 | public static final ImageIcon DISCORD_ICON = new ImageIcon(ImageUtil.loadImageResource(PLUGIN_CLASS, "discord.png"));
38 | public static final ImageIcon PATREON_ICON = new ImageIcon(ImageUtil.loadImageResource(PLUGIN_CLASS, "patreon.png"));
39 | public static final ImageIcon WEB_ICON = new ImageIcon(ImageUtil.loadImageResource(PLUGIN_CLASS, "web.png"));
40 | public static final ImageIcon TWITTER_ICON = new ImageIcon(ImageUtil.loadImageResource(PLUGIN_CLASS, "twitter.png"));
41 | public static final ImageIcon WARNING_ICON = new ImageIcon(ImageUtil.loadImageResource(PLUGIN_CLASS, "warning.png"));
42 | public static final ImageIcon STRONG_WARNING_ICON = new ImageIcon(ImageUtil.loadImageResource(PLUGIN_CLASS, "strong_warning.png"));
43 | public static final ImageIcon ERROR_ICON = new ImageIcon(ImageUtil.loadImageResource(PLUGIN_CLASS, "error.png"));
44 |
45 | // Must not be ImageUtil.loadImageResource as it produces a static image
46 | public static final ImageIcon LOADING_SPINNER = new ImageIcon(Objects.requireNonNull(PLUGIN_CLASS.getResource("loading_spinner_darker.gif")));
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/botdetector/ui/NameAutocompleter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018, John Pettenger
3 | * Copyright (c) 2021, Ferrariic, Seltzer Bro, Cyborger1
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright notice, this
10 | * list of conditions and the following disclaimer.
11 | *
12 | * 2. Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 | package com.botdetector.ui;
28 |
29 | import com.botdetector.BotDetectorConfig;
30 | import com.google.common.collect.EvictingQueue;
31 | import com.google.inject.Inject;
32 | import java.awt.event.KeyEvent;
33 | import java.awt.event.KeyListener;
34 | import java.util.Arrays;
35 | import java.util.Objects;
36 | import java.util.Optional;
37 | import java.util.regex.Pattern;
38 | import javax.annotation.Nullable;
39 | import javax.inject.Singleton;
40 | import javax.swing.SwingUtilities;
41 | import javax.swing.text.BadLocationException;
42 | import javax.swing.text.Document;
43 | import javax.swing.text.JTextComponent;
44 | import lombok.NonNull;
45 | import lombok.extern.slf4j.Slf4j;
46 | import net.runelite.api.FriendsChatManager;
47 | import net.runelite.api.Client;
48 | import net.runelite.api.Friend;
49 | import net.runelite.api.Nameable;
50 | import net.runelite.api.NameableContainer;
51 | import net.runelite.api.Player;
52 | import net.runelite.api.WorldView;
53 |
54 | @Slf4j
55 | @Singleton
56 | public class NameAutocompleter implements KeyListener
57 | {
58 | /**
59 | * Non-breaking space character.
60 | */
61 | private static final String NBSP = Character.toString((char) 160);
62 |
63 | /**
64 | * Character class for characters that cannot be in an RSN.
65 | */
66 | private static final Pattern INVALID_CHARS = Pattern.compile("[^a-zA-Z0-9_ -]");
67 |
68 | private static final int MAX_SEARCH_HISTORY = 25;
69 |
70 | private final Client client;
71 | private final BotDetectorConfig botDetectorConfig;
72 |
73 | private final EvictingQueue searchHistory = EvictingQueue.create(MAX_SEARCH_HISTORY);
74 |
75 | /**
76 | * The name currently being autocompleted.
77 | */
78 | private String autocompleteName;
79 |
80 | /**
81 | * Pattern for the name currently being autocompleted.
82 | */
83 | private Pattern autocompleteNamePattern;
84 |
85 | @Inject
86 | private NameAutocompleter(@Nullable Client client, BotDetectorConfig botDetectorConfig)
87 | {
88 | this.client = client;
89 | this.botDetectorConfig = botDetectorConfig;
90 | }
91 |
92 | @Override
93 | public void keyPressed(KeyEvent e)
94 | {
95 |
96 | }
97 |
98 | @Override
99 | public void keyReleased(KeyEvent e)
100 | {
101 |
102 | }
103 |
104 | @Override
105 | public void keyTyped(KeyEvent e)
106 | {
107 | if (!botDetectorConfig.panelAutocomplete())
108 | {
109 | return;
110 | }
111 |
112 | final JTextComponent input = (JTextComponent) e.getSource();
113 | final String inputText = input.getText();
114 |
115 | // Only autocomplete if the selection end is at the end of the text.
116 | if (input.getSelectionEnd() != inputText.length())
117 | {
118 | return;
119 | }
120 |
121 | // Character to be inserted at the selection start.
122 | final String charToInsert = Character.toString(e.getKeyChar());
123 |
124 | // Don't attempt to autocomplete if the name is invalid.
125 | // This condition is also true when the user presses a key like backspace.
126 | if (INVALID_CHARS.matcher(charToInsert).find()
127 | || INVALID_CHARS.matcher(inputText).find())
128 | {
129 | return;
130 | }
131 |
132 | // Check if we are already autocompleting.
133 | if (autocompleteName != null && autocompleteNamePattern.matcher(inputText).matches())
134 | {
135 | if (isExpectedNext(input, charToInsert))
136 | {
137 | try
138 | {
139 | // Insert the character and move the selection.
140 | final int insertIndex = input.getSelectionStart();
141 | Document doc = input.getDocument();
142 | doc.remove(insertIndex, 1);
143 | doc.insertString(insertIndex, charToInsert, null);
144 | input.select(insertIndex + 1, input.getSelectionEnd());
145 | }
146 | catch (BadLocationException ex)
147 | {
148 | log.warn("Could not insert character.", ex);
149 | }
150 |
151 | // Prevent default behavior.
152 | e.consume();
153 | }
154 | else // Character to insert does not match current autocompletion. Look for another name.
155 | {
156 | newAutocomplete(e);
157 | }
158 | }
159 | else // Search for a name to autocomplete
160 | {
161 | newAutocomplete(e);
162 | }
163 | }
164 |
165 | private void newAutocomplete(KeyEvent e)
166 | {
167 | final JTextComponent input = (JTextComponent) e.getSource();
168 | final String inputText = input.getText();
169 | final String nameStart = inputText.substring(0, input.getSelectionStart()) + e.getKeyChar();
170 |
171 | if (findAutocompleteName(nameStart))
172 | {
173 | // Assert this.autocompleteName != null
174 | final String name = this.autocompleteName;
175 | SwingUtilities.invokeLater(() ->
176 | {
177 | try
178 | {
179 | input.getDocument().insertString(
180 | nameStart.length(),
181 | name.substring(nameStart.length()),
182 | null);
183 | input.select(nameStart.length(), name.length());
184 | }
185 | catch (BadLocationException ex)
186 | {
187 | log.warn("Could not autocomplete name.", ex);
188 | }
189 | });
190 | }
191 | }
192 |
193 | private boolean findAutocompleteName(String nameStart)
194 | {
195 | final Pattern pattern;
196 | Optional autocompleteName;
197 |
198 | // Pattern to match names that start with nameStart.
199 | // Allows spaces to be represented as common whitespaces, underscores,
200 | // hyphens, or non-breaking spaces.
201 | // Matching non-breaking spaces is necessary because the API
202 | // returns non-breaking spaces when a name has whitespace.
203 | pattern = Pattern.compile(
204 | "(?i)^" + nameStart.replaceAll("[ _-]", "[ _" + NBSP + "-]") + ".+?");
205 |
206 | if (client == null)
207 | {
208 | return false;
209 | }
210 |
211 | // Search all previous successful queries
212 | autocompleteName = searchHistory.stream()
213 | .filter(n -> pattern.matcher(n).matches())
214 | .findFirst();
215 |
216 | // Search friends if previous searches weren't matched
217 | if (!autocompleteName.isPresent())
218 | {
219 | NameableContainer friendContainer = client.getFriendContainer();
220 | if (friendContainer != null)
221 | {
222 | autocompleteName = Arrays.stream(friendContainer.getMembers())
223 | .map(Nameable::getName)
224 | .filter(n -> pattern.matcher(n).matches())
225 | .findFirst();
226 | }
227 | }
228 |
229 | // Search friends chat if a friend wasn't found
230 | if (!autocompleteName.isPresent())
231 | {
232 | final FriendsChatManager friendsChatManager = client.getFriendsChatManager();
233 | if (friendsChatManager != null)
234 | {
235 | autocompleteName = Arrays.stream(friendsChatManager.getMembers())
236 | .map(Nameable::getName)
237 | .filter(n -> pattern.matcher(n).matches())
238 | .findFirst();
239 | }
240 | }
241 |
242 | // Search cached players if a friend wasn't found
243 | if (!autocompleteName.isPresent())
244 | {
245 | final WorldView wv = client.getTopLevelWorldView();
246 | if (wv != null)
247 | {
248 | autocompleteName = wv.players().stream()
249 | .filter(Objects::nonNull)
250 | .map(Player::getName)
251 | .filter(Objects::nonNull)
252 | .filter(n -> pattern.matcher(n).matches())
253 | .findFirst();
254 | }
255 | }
256 |
257 | if (autocompleteName.isPresent())
258 | {
259 | this.autocompleteName = autocompleteName.get().replace(NBSP, " ");
260 | this.autocompleteNamePattern = Pattern.compile(
261 | "(?i)^" + this.autocompleteName.replaceAll("[ _-]", "[ _-]") + "$");
262 | }
263 | else
264 | {
265 | this.autocompleteName = null;
266 | this.autocompleteNamePattern = null;
267 | }
268 |
269 | return autocompleteName.isPresent();
270 | }
271 |
272 | void addToSearchHistory(@NonNull String name)
273 | {
274 | if (!searchHistory.contains(name))
275 | {
276 | searchHistory.offer(name);
277 | }
278 | }
279 |
280 | private boolean isExpectedNext(JTextComponent input, String nextChar)
281 | {
282 | String expected;
283 | if (input.getSelectionStart() < input.getSelectionEnd())
284 | {
285 | try
286 | {
287 | expected = input.getText(input.getSelectionStart(), 1);
288 | }
289 | catch (BadLocationException ex)
290 | {
291 | log.warn("Could not get first character from input selection.", ex);
292 | return false;
293 | }
294 | }
295 | else
296 | {
297 | expected = "";
298 | }
299 | return nextChar.equalsIgnoreCase(expected);
300 | }
301 | }
302 |
--------------------------------------------------------------------------------
/src/main/java/com/botdetector/ui/PanelFontType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021, Ferrariic, Seltzer Bro, Cyborger1
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | *
11 | * 2. Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | package com.botdetector.ui;
27 |
28 | public enum PanelFontType
29 | {
30 | SMALL,
31 | NORMAL,
32 | BOLD
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/botdetector/ui/components/ComboBoxSelfTextTooltipListRenderer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021, Ferrariic, Seltzer Bro, Cyborger1
3 | * Copyright (c) 2017, Psikoi
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright notice, this
10 | * list of conditions and the following disclaimer.
11 | *
12 | * 2. Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 | package com.botdetector.ui.components;
28 |
29 | import java.awt.Color;
30 | import java.awt.Component;
31 | import javax.swing.JLabel;
32 | import javax.swing.JList;
33 | import javax.swing.ListCellRenderer;
34 | import javax.swing.border.EmptyBorder;
35 | import net.runelite.client.ui.ColorScheme;
36 |
37 | public final class ComboBoxSelfTextTooltipListRenderer extends JLabel implements ListCellRenderer
38 | {
39 | @Override
40 | public Component getListCellRendererComponent(JList extends T> list, T o, int index, boolean isSelected, boolean cellHasFocus)
41 | {
42 | if (isSelected)
43 | {
44 | setBackground(ColorScheme.DARK_GRAY_COLOR);
45 | setForeground(Color.WHITE);
46 | }
47 | else
48 | {
49 | setBackground(list.getBackground());
50 | setForeground(ColorScheme.LIGHT_GRAY_COLOR);
51 | }
52 |
53 | setBorder(new EmptyBorder(0, 0, 0, 0));
54 |
55 | setText(o.toString());
56 | setToolTipText(o.toString());
57 |
58 | return this;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/botdetector/ui/components/JLimitedTextArea.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016 under CC BY 3.0, Francisco J. Güemes Sevilla
3 | * Copyright (c) 2021 under BSD 2, Ferrariic, Seltzer Bro, Cyborger1
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright notice, this
10 | * list of conditions and the following disclaimer.
11 | *
12 | * 2. Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 | package com.botdetector.ui.components;
28 |
29 | import javax.swing.JTextArea;
30 | import javax.swing.text.AttributeSet;
31 | import javax.swing.text.BadLocationException;
32 | import javax.swing.text.Document;
33 | import javax.swing.text.PlainDocument;
34 |
35 | /**
36 | * An extension of {@link JTextArea} that automatically implements
37 | * a default {@link Document} model that limits the number of characters
38 | * that can be entered to the given {@code limit} in {@link #JLimitedTextArea(int)}.
39 | */
40 | public class JLimitedTextArea extends JTextArea
41 | {
42 | private final int limit;
43 |
44 | /**
45 | * Instanciates a {@link JTextArea} implementing a default {@link Document} model
46 | * that limits the number of characters that can be entered.
47 | * @param limit The maximum number of characters that can be entered in the underlying {@link JTextArea}.
48 | */
49 | public JLimitedTextArea(int limit)
50 | {
51 | super();
52 | this.limit = limit;
53 | }
54 |
55 | @Override
56 | protected Document createDefaultModel()
57 | {
58 | return new LimitDocument();
59 | }
60 |
61 | private class LimitDocument extends PlainDocument
62 | {
63 | @Override
64 | public void insertString( int offset, String str, AttributeSet attr ) throws BadLocationException
65 | {
66 | if (str == null) return;
67 |
68 | if ((getLength() + str.length()) <= limit)
69 | {
70 | super.insertString(offset, str, attr);
71 | }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/resources/com/botdetector/bot-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bot-detector/bot-detector/bc410b29edc2545fb8c25941ebbeabcd74b86aef/src/main/resources/com/botdetector/bot-icon.png
--------------------------------------------------------------------------------
/src/main/resources/com/botdetector/ui/discord.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bot-detector/bot-detector/bc410b29edc2545fb8c25941ebbeabcd74b86aef/src/main/resources/com/botdetector/ui/discord.png
--------------------------------------------------------------------------------
/src/main/resources/com/botdetector/ui/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bot-detector/bot-detector/bc410b29edc2545fb8c25941ebbeabcd74b86aef/src/main/resources/com/botdetector/ui/error.png
--------------------------------------------------------------------------------
/src/main/resources/com/botdetector/ui/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bot-detector/bot-detector/bc410b29edc2545fb8c25941ebbeabcd74b86aef/src/main/resources/com/botdetector/ui/github.png
--------------------------------------------------------------------------------
/src/main/resources/com/botdetector/ui/loading_spinner_darker.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bot-detector/bot-detector/bc410b29edc2545fb8c25941ebbeabcd74b86aef/src/main/resources/com/botdetector/ui/loading_spinner_darker.gif
--------------------------------------------------------------------------------
/src/main/resources/com/botdetector/ui/patreon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bot-detector/bot-detector/bc410b29edc2545fb8c25941ebbeabcd74b86aef/src/main/resources/com/botdetector/ui/patreon.png
--------------------------------------------------------------------------------
/src/main/resources/com/botdetector/ui/strong_warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bot-detector/bot-detector/bc410b29edc2545fb8c25941ebbeabcd74b86aef/src/main/resources/com/botdetector/ui/strong_warning.png
--------------------------------------------------------------------------------
/src/main/resources/com/botdetector/ui/twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bot-detector/bot-detector/bc410b29edc2545fb8c25941ebbeabcd74b86aef/src/main/resources/com/botdetector/ui/twitter.png
--------------------------------------------------------------------------------
/src/main/resources/com/botdetector/ui/warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bot-detector/bot-detector/bc410b29edc2545fb8c25941ebbeabcd74b86aef/src/main/resources/com/botdetector/ui/warning.png
--------------------------------------------------------------------------------
/src/main/resources/com/botdetector/ui/web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bot-detector/bot-detector/bc410b29edc2545fb8c25941ebbeabcd74b86aef/src/main/resources/com/botdetector/ui/web.png
--------------------------------------------------------------------------------
/src/test/java/com/botdetector/BotDetectorPluginTest.java:
--------------------------------------------------------------------------------
1 | package com.botdetector;
2 |
3 | import net.runelite.client.RuneLite;
4 | import net.runelite.client.externalplugins.ExternalPluginManager;
5 |
6 | public class BotDetectorPluginTest
7 | {
8 | public static void main(String[] args) throws Exception
9 | {
10 | ExternalPluginManager.loadBuiltin(BotDetectorPlugin.class);
11 | RuneLite.main(args);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------