├── .github
├── FUNDING.yml
└── workflows
│ └── codeql-analysis.yml
├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
└── main
├── java
└── nl
│ └── corwindev
│ └── streamervschat
│ ├── command
│ ├── DiscordReload.java
│ ├── TestCommand.java
│ ├── TwitchReload.java
│ └── YouTubeReload.java
│ ├── commands.java
│ ├── discord
│ └── DiscordConnectionHelper.java
│ ├── main.java
│ ├── objects
│ ├── JdaFilter.java
│ └── UpdateChecker.java
│ ├── twitch
│ ├── TwitchConnectionHelper.java
│ └── TwitchEvents.java
│ └── youtube
│ └── YouTubeConnectionHelper.java
└── resources
├── config.yml
└── plugin.yml
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [CorwinDev]
4 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ "master" ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ "master" ]
20 | schedule:
21 | - cron: '31 3 * * 1'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'java' ]
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
38 |
39 | steps:
40 | - name: Checkout repository
41 | uses: actions/checkout@v3
42 |
43 | # Initializes the CodeQL tools for scanning.
44 | - name: Initialize CodeQL
45 | uses: github/codeql-action/init@v2
46 | with:
47 | languages: ${{ matrix.language }}
48 | # If you wish to specify custom queries, you can do so here or in a config file.
49 | # By default, queries listed here will override any specified in a config file.
50 | # Prefix the list here with "+" to use these queries and those in the config file.
51 |
52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
53 | # queries: security-extended,security-and-quality
54 |
55 |
56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
57 | # If this step fails, then you should remove it and run the build manually (see below)
58 | - name: Autobuild
59 | uses: github/codeql-action/autobuild@v2
60 |
61 | # ℹ️ Command-line programs to run using the OS shell.
62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
63 |
64 | # If the Autobuild fails above, remove it and uncomment the following three lines.
65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
66 |
67 | # - run: |
68 | # echo "Run, Build Application using script"
69 | # ./location_of_script_within_repo/buildscript.sh
70 |
71 | - name: Perform CodeQL Analysis
72 | uses: github/codeql-action/analyze@v2
73 |
74 | - name: Setup Java JDK
75 | uses: actions/setup-java@v3.4.1
76 | with:
77 | java-version: '11'
78 | distribution: 'adopt'
79 | - name: Run the Maven verify phase
80 | run: mvn --batch-mode --update-snapshots verify
81 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # User-specific stuff
2 | .idea/
3 |
4 | *.iml
5 | *.ipr
6 | *.iws
7 |
8 | # IntelliJ
9 | out/
10 |
11 | # Compiled class file
12 | *.class
13 |
14 | # Log file
15 | *.log
16 |
17 | # BlueJ files
18 | *.ctxt
19 |
20 | # Package Files #
21 | *.jar
22 | *.war
23 | *.nar
24 | *.ear
25 | *.zip
26 | *.tar.gz
27 | *.rar
28 |
29 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
30 | hs_err_pid*
31 |
32 | *~
33 |
34 | # temporary files which can be created if a process still has a handle open of a deleted file
35 | .fuse_hidden*
36 |
37 | # KDE directory preferences
38 | .directory
39 |
40 | # Linux trash folder which might appear on any partition or disk
41 | .Trash-*
42 |
43 | # .nfs files are created when an open file is removed but is still being accessed
44 | .nfs*
45 |
46 | # General
47 | .DS_Store
48 | .AppleDouble
49 | .LSOverride
50 |
51 | # Icon must end with two \r
52 | Icon
53 |
54 | # Thumbnails
55 | ._*
56 |
57 | # Files that might appear in the root of a volume
58 | .DocumentRevisions-V100
59 | .fseventsd
60 | .Spotlight-V100
61 | .TemporaryItems
62 | .Trashes
63 | .VolumeIcon.icns
64 | .com.apple.timemachine.donotpresent
65 |
66 | # Directories potentially created on remote AFP share
67 | .AppleDB
68 | .AppleDesktop
69 | Network Trash Folder
70 | Temporary Items
71 | .apdisk
72 |
73 | # Windows thumbnail cache files
74 | Thumbs.db
75 | Thumbs.db:encryptable
76 | ehthumbs.db
77 | ehthumbs_vista.db
78 |
79 | # Dump file
80 | *.stackdump
81 |
82 | # Folder config file
83 | [Dd]esktop.ini
84 |
85 | # Recycle Bin used on file shares
86 | $RECYCLE.BIN/
87 |
88 | # Windows Installer files
89 | *.cab
90 | *.msi
91 | *.msix
92 | *.msm
93 | *.msp
94 |
95 | # Windows shortcuts
96 | *.lnk
97 |
98 | target/
99 |
100 | pom.xml.tag
101 | pom.xml.releaseBackup
102 | pom.xml.versionsBackup
103 | pom.xml.next
104 |
105 | release.properties
106 | dependency-reduced-pom.xml
107 | buildNumber.properties
108 | .mvn/timing.properties
109 | .mvn/wrapper/maven-wrapper.jar
110 | .flattened-pom.xml
111 |
112 | # Common working directory
113 | run/
114 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 CorwinDev
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # StreamerVSChat
2 | StreamerVSChat is a open source project that allows you to play against your followers/subscribers.
3 | 
4 |
5 | The plugin contains over 30 commands, and is fully customizable.
6 |
7 | You can also add your own commands!
8 |
9 | ## How to use
10 | 1. Download the latest release from [here](https://github.com/CorwinDev/StreamerVSChat/releases)
11 | 2. Upload the file to your plugin folder
12 | 3. Start your server
13 | 4. Edit the config file
14 | 5. Restart/reload your server
15 |
16 | SUPPORT AT [DISCORD](https://discord.gg/KrTfebJhNH)
17 |
18 | ## How to configure
19 | 1. Open the config file
20 | 2. Change the settings
21 | Get your Twitch Client ID [here](https://twitchapps.com/tmi/)
22 | Get your YouTube API Key [here](https://console.developers.google.com/apis/credentials)
23 | Get your Discord Bot Token [here](https://discord.com/developers/applications)
24 | 3. Save the file
25 | 4. Restart/reload your server
26 |
27 | ## How to use the commands
28 | ### We have now ability to make custom commands!
29 | For more information, check out the [wiki](https://github.com/CorwinDev/StreamerVSChat/wiki#custom-commands-setup)
30 |
31 | We have over 20 commands that you can use to control the streamer:
32 | | Command | Description |
33 | | --- | --- |
34 | | !lava | Place lava under the streamer |
35 | | !anvil | Drops an anvil on the streamer |
36 | | !creepscare or !behindyou | Summons sound of creepers |
37 | | !dropall | Drops all items from the streamer |
38 | | !blindness | Gives the streamer blindness |
39 | | !lightning | Summons lightning on the streamer |
40 | | !fire | Sets the streamer on fire |
41 | | !explosion | Summons an explosion on the streamer |
42 | | !rain | Sets weather to rain |
43 | | !witherscare or !wither | Summons sound of wither |
44 | | !creeper | Summons a creeper on the streamer |
45 | | !zombie | Summons a zombie on the streamer |
46 | | !illness or !nausea | Gives streamer illness |
47 | | !slowness | Gives streamer slowness effect |
48 | | !badluck | Gives streamer BadLuck effect |
49 | | !mining or !miningfatique | Gives streamer miningfatigue |
50 | | !hunger | Gives streamer hunger |
51 | | !fly or !levitate | Lets the streamer fly |
52 | | jumpboost | Gives streamer jumpboost effect |
53 | | !feed | Feeds the streamer |
54 | | !heal | Heals the player |
55 | | !randomeffect or !randompoison | Gives streamer random poison |
56 | | !fireball | Shoots fireball at streamer |
57 | | !drop | Drops item in main hand |
58 | | !silverfish | Summons silverfish on streamer |
59 | | !vex | Summons vex on streamer |
60 | | !chicken | Summons chicken on streamer |
61 | | !bee | Summons angry bee on streamer |
62 | | !day | Sets time to day |
63 | | !night | Sets time to night |
64 | | !peaceful | Sets difficulty to peaceful |
65 | | !hard | Sets difficulty to hard |
66 | | !easy | Sets difficulty to easy |
67 | | !rename ~Name~ | Renames the streamer item currently holding|
68 | // All ! above can be replaced with your custom prefix
69 | // More commands coming soon //
70 |
71 | 
72 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | StreamerVSChat
8 | StreamerVSChat
9 | 2.2
10 | jar
11 |
12 | Streamer vs Chat
13 |
14 |
15 | 1.8
16 | UTF-8
17 | UTF-8
18 |
19 |
20 |
21 |
22 |
23 | maven-compiler-plugin
24 | 3.8.1
25 |
26 | 1.8
27 | 1.8
28 |
29 |
30 |
31 | maven-shade-plugin
32 | 3.2.4
33 |
34 |
35 |
36 | org.bstats
37 | nl.corwindev.streamervschat.main
38 |
39 |
40 |
41 |
42 | nl.corwindev.streamervschat.main
43 |
44 |
45 |
46 | false
47 |
48 |
49 |
50 | package
51 |
52 | shade
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | spigotmc-repo
63 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/
64 |
65 |
66 | sonatype
67 | https://oss.sonatype.org/content/groups/public/
68 |
69 |
70 | dv8tion
71 | m2-dv8tion
72 | https://m2.dv8tion.net/releases
73 |
74 |
75 | central
76 | https://repo1.maven.org/maven2
77 |
78 |
79 |
80 |
81 |
82 | org.spigotmc
83 | spigot-api
84 | 1.16.5-R0.1-SNAPSHOT
85 | provided
86 |
87 |
88 | org.apache.logging.log4j
89 | log4j-core
90 | 2.18.0
91 |
92 |
93 | net.dv8tion
94 | JDA
95 | 4.3.0_349
96 |
97 |
98 | club.minnced
99 | opus-java
100 |
101 |
102 | org.slf4j
103 | *
104 |
105 |
106 |
107 |
108 | com.github.twitch4j
109 | twitch4j-chat
110 | 1.11.0
111 |
112 |
113 | club.minnced
114 | opus-java
115 |
116 |
117 | org.slf4j
118 | *
119 |
120 |
121 | commons-lang
122 | *
123 |
124 |
125 | io.github.openfeign
126 | *
127 |
128 |
129 |
130 |
131 | com.google.apis
132 | google-api-services-youtube
133 | v3-rev182-1.22.0
134 |
135 |
136 | org.bstats
137 | bstats-bukkit
138 | 3.0.0
139 | compile
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/src/main/java/nl/corwindev/streamervschat/command/DiscordReload.java:
--------------------------------------------------------------------------------
1 | package nl.corwindev.streamervschat.command;
2 |
3 | import nl.corwindev.streamervschat.discord.DiscordConnectionHelper;
4 | import nl.corwindev.streamervschat.main;
5 | import org.bukkit.ChatColor;
6 | import org.bukkit.command.Command;
7 | import org.bukkit.command.CommandExecutor;
8 | import org.bukkit.command.CommandSender;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | public class DiscordReload implements CommandExecutor {
12 | @Override
13 | public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
14 | if(!main.plugin.getConfig().getBoolean("discord.enabled")){
15 | commandSender.sendMessage(ChatColor.RED + "Discord is not enabled.");
16 | return true;
17 | }
18 | DiscordConnectionHelper.reload();
19 | commandSender.sendMessage(ChatColor.GREEN + "Reloaded Discord connection.");
20 | return true;
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/java/nl/corwindev/streamervschat/command/TestCommand.java:
--------------------------------------------------------------------------------
1 | package nl.corwindev.streamervschat.command;
2 |
3 | import org.bukkit.ChatColor;
4 | import org.bukkit.command.Command;
5 | import org.bukkit.command.CommandExecutor;
6 | import org.bukkit.command.CommandSender;
7 | import org.jetbrains.annotations.NotNull;
8 | import nl.corwindev.streamervschat.commands;
9 |
10 | import java.util.Arrays;
11 |
12 | public class TestCommand implements CommandExecutor {
13 | @Override
14 | public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
15 | if(command.getName().equalsIgnoreCase("testcommand")){
16 | // Check if args are empty
17 | if(commandSender.hasPermission("nl.corwindev.streamervschat.streamer")){
18 | if(strings.length == 0){
19 | commandSender.sendMessage(ChatColor.RED + "Correct usage: /testcommand ");
20 | return false;
21 | }
22 | commands.UserList.add(commandSender.getName());
23 | if(strings[0].equalsIgnoreCase("rename")){
24 | System.out.println(Arrays.toString(strings));
25 | commands.commandList.add(strings[0] + " " + strings[1]);
26 | }else{
27 | commands.commandList.add(strings[0]);
28 | }
29 | commandSender.sendMessage(ChatColor.GREEN + "Added command: " + strings[0] + " to queue;");
30 | return true;
31 | }
32 | }
33 | return true;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/nl/corwindev/streamervschat/command/TwitchReload.java:
--------------------------------------------------------------------------------
1 | package nl.corwindev.streamervschat.command;
2 |
3 | import nl.corwindev.streamervschat.main;
4 | import nl.corwindev.streamervschat.twitch.TwitchConnectionHelper;
5 | import org.bukkit.ChatColor;
6 | import org.bukkit.command.Command;
7 | import org.bukkit.command.CommandExecutor;
8 | import org.bukkit.command.CommandSender;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | public class TwitchReload implements CommandExecutor {
12 | @Override
13 | public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
14 | if(!main.plugin.getConfig().getBoolean("twitch.enabled")){
15 | commandSender.sendMessage(ChatColor.RED + "Twitch is not enabled.");
16 | return true;
17 | }
18 | TwitchConnectionHelper.reload();
19 | commandSender.sendMessage(ChatColor.GREEN + "Reloaded Twitch connection.");
20 | return true;
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/java/nl/corwindev/streamervschat/command/YouTubeReload.java:
--------------------------------------------------------------------------------
1 | package nl.corwindev.streamervschat.command;
2 |
3 | import nl.corwindev.streamervschat.main;
4 | import nl.corwindev.streamervschat.youtube.YouTubeConnectionHelper;
5 | import org.bukkit.ChatColor;
6 | import org.bukkit.command.Command;
7 | import org.bukkit.command.CommandExecutor;
8 | import org.bukkit.command.CommandSender;
9 | import org.jetbrains.annotations.NotNull;
10 |
11 | public class YouTubeReload implements CommandExecutor {
12 | @Override
13 | public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
14 | if(!main.plugin.getConfig().getBoolean("youtube.enabled")){
15 | commandSender.sendMessage(ChatColor.RED + "YouTube is not enabled.");
16 | return true;
17 | }
18 | YouTubeConnectionHelper.reload();
19 | commandSender.sendMessage(ChatColor.GREEN + "Reloaded YouTube connection.");
20 | return true;
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/java/nl/corwindev/streamervschat/commands.java:
--------------------------------------------------------------------------------
1 | package nl.corwindev.streamervschat;
2 |
3 | import net.dv8tion.jda.api.entities.User;
4 | import net.md_5.bungee.api.ChatMessageType;
5 | import net.md_5.bungee.api.chat.TextComponent;
6 | import org.bukkit.*;
7 | import org.bukkit.block.Block;
8 | import org.bukkit.block.BlockFace;
9 | import org.bukkit.entity.*;
10 | import org.bukkit.inventory.Inventory;
11 | import org.bukkit.inventory.ItemStack;
12 | import org.bukkit.inventory.meta.ItemMeta;
13 | import org.bukkit.potion.PotionEffect;
14 | import org.bukkit.potion.PotionEffectType;
15 | import org.bukkit.scheduler.BukkitTask;
16 | import org.bukkit.util.Vector;
17 |
18 | import java.util.*;
19 | import java.util.concurrent.ThreadLocalRandom;
20 |
21 | import static nl.corwindev.streamervschat.main.plugin;
22 |
23 | public class commands {
24 | public static List commandList = new ArrayList();
25 | public static List UserList = new ArrayList();
26 | public static List cooldowns = new ArrayList();
27 |
28 | public static void start() {
29 | BukkitTask task = Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
30 | @Override
31 | public void run() {
32 | startCommand();
33 | }
34 | }, plugin.getConfig().getInt("commands.delay") * 20L, plugin.getConfig().getInt("commands.delay") * 20L);
35 | }
36 | public static void startCommand(){
37 | Random rand = new Random();
38 | if (commandList.size() == 0) {
39 | return;
40 | }
41 | int randomCommand = rand.nextInt(commandList.size());
42 | String command = commandList.get(randomCommand);
43 | runCmd(command, UserList.get(randomCommand));
44 | }
45 | public static void runCmd(String command, String random) {
46 | if (Objects.requireNonNull(plugin.getConfig().getList("blacklist")).contains(command)) {
47 | return;
48 | }
49 | int index = commandList.indexOf(command);
50 | if(plugin.getConfig().getString("cooldowns." + command) != null){
51 | if(cooldowns.contains(command)){
52 | commandList.remove(index);
53 | UserList.remove(index);
54 | startCommand();
55 | return;
56 | }else{
57 | cooldowns.add(command);
58 | Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
59 | @Override
60 | public void run() {
61 | cooldowns.remove(command);
62 | }
63 | }, plugin.getConfig().getInt("cooldowns." + command) * 20L);
64 | }
65 | }
66 | if (Objects.equals(command, "lava")) {
67 | commands.lava();
68 | } else if (Objects.equals(command, "anvil")) {
69 | commands.anvil();
70 | } else if (Objects.equals(command, "creepscare") || Objects.equals(command, "behindyou")) {
71 | commands.creepsound();
72 | } else if (Objects.equals(command, "dropall")) {
73 | commands.dropall();
74 | } else if (Objects.equals(command, "blindness")) {
75 | commands.blindness();
76 | } else if (Objects.equals(command, "lightning")) {
77 | commands.lightning();
78 | } else if (Objects.equals(command, "fire")) {
79 | commands.fire();
80 | } else if (Objects.equals(command, "explosion")) {
81 | commands.explosion();
82 | } else if (Objects.equals(command, "rain")) {
83 | commands.rain();
84 | } else if (Objects.equals(command, "hunger")) {
85 | commands.hunger();
86 | } else if (Objects.equals(command, "witherscare") || Objects.equals(command, "wither")) {
87 | commands.wither();
88 | } else if (Objects.equals(command, "creeper")) {
89 | commands.creeper(UserList.get(index));
90 | } else if (Objects.equals(command, "zombie")) {
91 | commands.zombie(UserList.get(index));
92 | } else if (Objects.equals(command, "illness") || Objects.equals(command, "nausea")) {
93 | commands.nausea();
94 | } else if (Objects.equals(command, "slowness")) {
95 | commands.slowness();
96 | } else if (Objects.equals(command, "badluck")) {
97 | commands.badluck();
98 | } else if (Objects.equals(command, "mining") || Objects.equals(command, "miningfatigue")) {
99 | commands.miningfatigue();
100 | } else if (Objects.equals(command, "heal")) {
101 | commands.heal();
102 | } else if (Objects.equals(command, "feed")) {
103 | commands.feed();
104 | } else if (Objects.equals(command, "jumpboost")) {
105 | commands.jumpboost();
106 | } else if (Objects.equals(command, "levitate") || Objects.equals(command, "fly")) {
107 | commands.fly();
108 | } else if (Objects.equals(command, "randomeffect") || Objects.equals(command, "randompoison")) {
109 | commands.randomeffect();
110 | } else if (Objects.equals(command, "fireball")) {
111 | commands.fireball();
112 | } else if (Objects.equals(command, "drop")) {
113 | commands.drop();
114 | } else if (Objects.equals(command, "silverfish")) {
115 | commands.silverfish(UserList.get(index));
116 | } else if (Objects.equals(command, "vex")) {
117 | commands.vex(UserList.get(index));
118 | } else if (Objects.equals(command, "chicken")) {
119 | commands.chicken(UserList.get(index));
120 | } else if (Objects.equals(command, "bee")) {
121 | commands.bee(UserList.get(index));
122 | }else if(Objects.equals(command, "day")){
123 | commands.day();
124 | }else if(Objects.equals(command, "night")) {
125 | commands.night();
126 | }else if(Objects.equals(command, "peaceful")) {
127 | commands.peaceful();
128 | }else if(Objects.equals(command, "hard")) {
129 | commands.hard();
130 | }else if(Objects.equals(command, "easy")) {
131 | commands.easy();
132 | }else if(command.startsWith("rename")){
133 | commands.rename(command);
134 | } else {
135 | if(!commands.custom(command, UserList.get(index))){
136 | commandList.remove(index);
137 | UserList.remove(index);
138 | startCommand();
139 | return;
140 | }
141 | }
142 | for (Player player : getPlayers()) {
143 | String hotbar = plugin.getConfig().getString("hotbar");
144 | if(hotbar == null){
145 | hotbar = "§a§l%user%§r§a has executed the command: §l%command%";
146 | }
147 | player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(hotbar.replace("%command%", command).replace("%user%", random)));
148 | player.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent("§a§l" + random + "§r§a has executed the command: §l" + command));
149 | }
150 | commandList.clear();
151 | UserList.clear();
152 | }
153 |
154 | public static String name = "nl.corwindev.streamervschat";
155 | public static Integer duration = plugin.getConfig().getInt("poison-duration");
156 |
157 | public static boolean has(Player player, String permission) {
158 | return player == null || player.hasPermission(name + "." + permission) || player.hasPermission(name + ".*");
159 | }
160 |
161 | public static Collection getPlayers() {
162 | Collection players = new ArrayList<>();
163 | if (Objects.equals(plugin.getConfig().getString("affected-players"), "all")) {
164 | return (Collection) Bukkit.getOnlinePlayers();
165 | } else if (Objects.equals(plugin.getConfig().getString("affected-players"), "permission")) {
166 | for (Player player : Bukkit.getOnlinePlayers()) {
167 | if (has(player, "streamer")) {
168 | players.add(player);
169 | }
170 | }
171 | return players;
172 | } else {
173 | return (Collection) Bukkit.getOnlinePlayers();
174 | }
175 | }
176 |
177 |
178 | public static void lava() {
179 | for (Player player : getPlayers()) {
180 | Block playerBlock = player.getLocation().getBlock();
181 | Block blockUnder = playerBlock.getRelative(BlockFace.DOWN);
182 | // Set block to lava
183 | blockUnder.setType(org.bukkit.Material.LAVA);
184 | }
185 | }
186 |
187 | public static void anvil() {
188 | for (Player player : getPlayers()) {
189 | FallingBlock anvil = player.getWorld().spawnFallingBlock(player.getLocation().add(0, 16, 0), Bukkit.createBlockData(Material.ANVIL));
190 | anvil.setGravity(true);
191 | anvil.setHurtEntities(true);
192 | anvil.setFallDistance(20);
193 | anvil.setDropItem(false);
194 | player.getWorld().playSound(player.getLocation(), "minecraft:block.anvil.land", 100, 1);
195 | }
196 | }
197 |
198 | public static void creepsound() {
199 | for (Player player : getPlayers()) {
200 | player.getWorld().playSound(player.getLocation(), "minecraft:entity.creeper.primed", 100, 1);
201 | player.getWorld().playSound(player.getLocation(), "minecraft:entity.creeper.primed", 100, 1);
202 | }
203 | }
204 |
205 | public static void dropall() {
206 | for (Player player : getPlayers()) {
207 | Location loc = player.getLocation().clone();
208 | Inventory inv = player.getInventory();
209 | for (ItemStack item : inv.getContents()) {
210 | if (item != null) {
211 | loc.getWorld().dropItemNaturally(loc, item.clone());
212 | }
213 | }
214 | inv.clear();
215 | }
216 | }
217 |
218 | public static void blindness() {
219 | for (Player player : getPlayers()) {
220 | player.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.BLINDNESS, duration * 20, 1));
221 | }
222 | }
223 |
224 | public static void lightning() {
225 | for (Player player : getPlayers()) {
226 | player.getWorld().strikeLightning(player.getLocation());
227 | }
228 | }
229 |
230 | public static void creeper(String user) {
231 | for (Player player : getPlayers()) {
232 | player.getWorld().spawn(player.getLocation(), org.bukkit.entity.Creeper.class).setCustomName("§c§l" + user);
233 | }
234 | }
235 |
236 | public static void zombie(String user) {
237 | for (Player player : getPlayers()) {
238 | player.getWorld().spawn(player.getLocation(), org.bukkit.entity.Zombie.class).setCustomName("§c§l" + user);
239 | }
240 | }
241 |
242 | public static void fire() {
243 | for (Player player : getPlayers()) {
244 | player.setFireTicks(20 * 10);
245 | }
246 | }
247 |
248 | public static void explosion() {
249 | for (Player player : getPlayers()) {
250 | TNTPrimed tnt = (TNTPrimed) player.getWorld().spawnEntity(player.getLocation(), EntityType.PRIMED_TNT);
251 | tnt.setFuseTicks(40);
252 | }
253 | }
254 |
255 | public static void rain() {
256 | for (Player player : getPlayers()) {
257 | player.getWorld().setStorm(true);
258 | }
259 | }
260 |
261 | public static void wither() {
262 | for (Player player : getPlayers()) {
263 | player.getWorld().playSound(player.getLocation(), "minecraft:entity.wither.spawn", 100, 1);
264 | }
265 | }
266 |
267 | public static void hunger() {
268 | for (Player player : getPlayers()) {
269 | player.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.HUNGER, duration * 20, 1));
270 | }
271 | }
272 |
273 | public static void badluck() {
274 | for (Player player : getPlayers()) {
275 | player.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.UNLUCK, duration * 20, 1));
276 | }
277 | }
278 |
279 | public static void nausea() {
280 | for (Player player : getPlayers()) {
281 | player.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.CONFUSION, duration * 20, 1));
282 | }
283 | }
284 |
285 | public static void slowness() {
286 | for (Player player : getPlayers()) {
287 | player.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.SLOW, duration * 20, 1));
288 | }
289 | }
290 |
291 | public static void miningfatigue() {
292 | for (Player player : getPlayers()) {
293 | player.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.SLOW_DIGGING, duration * 20, 1));
294 | }
295 | }
296 |
297 | public static void feed() {
298 | for (Player player : getPlayers()) {
299 | player.setFoodLevel(20);
300 | }
301 | }
302 |
303 | public static void heal() {
304 | //Gives the player regeneration and health boost 2
305 | for (Player player : getPlayers()) {
306 | player.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.REGENERATION, duration * 20, 1));
307 | player.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.HEALTH_BOOST, duration * 20, 1));
308 | }
309 | }
310 |
311 | public static void jumpboost() {
312 | for (Player player : getPlayers()) {
313 | player.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.JUMP, duration * 20, 1));
314 | }
315 | }
316 |
317 | public static void fly() {
318 | for (Player player : getPlayers()) {
319 | player.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.LEVITATION, duration * 20, 1));
320 | }
321 | }
322 |
323 | public static boolean custom(String command, String user) {
324 | String command1 = plugin.getConfig().getString("customcommands." + command + ".command");
325 | if (command1 != null) {
326 | Integer cooldown = plugin.getConfig().getInt("customcommands." + command + ".cooldown");
327 |
328 | if (cooldown != null) {
329 | if (cooldowns.contains(command)) {
330 | return false;
331 | }
332 | cooldowns.add(command);
333 | Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
334 | @Override
335 | public void run() {
336 | cooldowns.remove(command);
337 | }
338 | }, cooldown * 20);
339 | }
340 | for (Player player : getPlayers()) {
341 | String command2 = command1.replace("%player%", player.getName());
342 | String command3 = command2.replace("%user%", user);
343 | plugin.getLogger().info(command3);
344 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command2);
345 | }
346 | return true;
347 | }
348 | return false;
349 | }
350 |
351 | public static void randomeffect() {
352 | int rnd = ThreadLocalRandom.current().nextInt(PotionEffectType.values().length);
353 |
354 | for (Player player : getPlayers()) {
355 | player.getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.values()[rnd], 200, 1));
356 | }
357 | }
358 |
359 | public static void fireball() {
360 | for (Player player : getPlayers()) {
361 | // Send fireball to the player
362 | Location location = new Location(player.getWorld(), player.getLocation().getX(), player.getLocation().getY() + 20, player.getLocation().getZ());
363 | Vector vector = player.getLocation().toVector().subtract(location.toVector()).normalize();
364 | Fireball fire = (Fireball) location.getWorld().spawn(location, Fireball.class);
365 | fire.setDirection(vector);
366 | }
367 | }
368 |
369 | public static void drop() {
370 | for (Player player : getPlayers()) {
371 | ItemStack hand = player.getInventory().getItemInMainHand();
372 | player.getInventory().removeItem(hand);
373 | player.getWorld().dropItemNaturally(player.getLocation(), hand);
374 | }
375 | }
376 |
377 | public static void silverfish(String user) {
378 | for (Player player : getPlayers()) {
379 | player.getWorld().spawn(player.getLocation(), org.bukkit.entity.Silverfish.class).setCustomName("§c§l" + user);;
380 | }
381 | }
382 |
383 | public static void vex(String user) {
384 | for (Player player : getPlayers()) {
385 | player.getWorld().spawn(player.getLocation(), org.bukkit.entity.Vex.class).setCustomName("§c§l" + user);;
386 | }
387 | }
388 |
389 | public static void bee(String user) {
390 | for (Player player : getPlayers()) {
391 | // Make bee angry
392 | Bee bee = (Bee) player.getWorld().spawn(player.getLocation(), org.bukkit.entity.Bee.class);
393 | bee.setAnger(1000000);
394 | bee.setCustomName("§c§l" + user);
395 | bee.attack(player);
396 | }
397 | }
398 |
399 | public static void chicken(String user) {
400 | for (Player player : getPlayers()) {
401 | player.getWorld().spawn(player.getLocation(), org.bukkit.entity.Chicken.class).setCustomName("§c§l" + user);;
402 | }
403 | }
404 |
405 | public static void day() {
406 | for (Player player : getPlayers()) {
407 | player.getWorld().setTime(0);
408 | }
409 | }
410 |
411 | public static void night() {
412 | for (Player player : getPlayers()) {
413 | player.getWorld().setTime(14000);
414 | }
415 | }
416 |
417 | public static void peaceful() {
418 | for (Player player : getPlayers()) {
419 | player.getWorld().setDifficulty(Difficulty.PEACEFUL);
420 | }
421 | }
422 |
423 | public static void hard() {
424 | for (Player player : getPlayers()) {
425 | player.getWorld().setDifficulty(Difficulty.HARD);
426 | }
427 | }
428 |
429 | public static void easy() {
430 | for (Player player : getPlayers()) {
431 | player.getWorld().setDifficulty(Difficulty.EASY);
432 | }
433 | }
434 |
435 | public static void rename(String command) {
436 | String name = command.substring(7);
437 | for (Player player : getPlayers()) {
438 | ItemStack hand = player.getInventory().getItemInMainHand();
439 | ItemMeta meta = hand.getItemMeta();
440 | assert meta != null;
441 | int rnd = ThreadLocalRandom.current().nextInt(16);
442 | meta.setDisplayName(ChatColor.values()[rnd] + name);
443 | hand.setItemMeta(meta);
444 | }
445 | }
446 | }
--------------------------------------------------------------------------------
/src/main/java/nl/corwindev/streamervschat/discord/DiscordConnectionHelper.java:
--------------------------------------------------------------------------------
1 | package nl.corwindev.streamervschat.discord;
2 |
3 | import net.dv8tion.jda.api.JDA;
4 | import net.dv8tion.jda.api.JDABuilder;
5 | import net.dv8tion.jda.api.entities.*;
6 | import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
7 | import net.dv8tion.jda.api.hooks.ListenerAdapter;
8 |
9 | import javax.security.auth.login.LoginException;
10 |
11 | import nl.corwindev.streamervschat.main;
12 |
13 |
14 | import nl.corwindev.streamervschat.commands;
15 |
16 | public class DiscordConnectionHelper {
17 | public static JDA api;
18 |
19 | public void main() throws LoginException, InterruptedException {
20 | api = JDABuilder.createDefault(main.plugin.getConfig().getString("discord.token"))
21 | .addEventListeners(new DiscordConnectionHelper.Listeners())
22 | .setContextEnabled(false)
23 | .build().awaitReady();
24 | }
25 |
26 | public static boolean isConnected() {
27 | if (api.getStatus() == JDA.Status.CONNECTED) {
28 | return true;
29 | } else {
30 | return false;
31 | }
32 | }
33 |
34 | public class Listeners extends ListenerAdapter {
35 | @Override
36 | public void onMessageReceived(MessageReceivedEvent event) {
37 | // Get the channel the message was sent in
38 | TextChannel channel = event.getTextChannel();
39 | if (channel.getId().equals(main.plugin.getConfig().getString("discord.channel"))) {
40 | if (event.getAuthor().isBot()) return;
41 | Message message = event.getMessage();
42 | String content = message.getContentRaw();
43 | if (content.contains(main.plugin.getConfig().getString("commands.prefix"))) {
44 | commands.UserList.add(event.getAuthor().getName());
45 | commands.commandList.add(content.replace(main.plugin.getConfig().getString("commands.prefix"), ""));
46 | }
47 | }
48 | }
49 | }
50 |
51 | public static void reload(){
52 | main.plugin.getLogger().info("[Discord] Reloading...");
53 | main.plugin.reloadConfig();
54 | if(api.getStatus() == JDA.Status.CONNECTED){
55 | api.shutdown();
56 | }
57 | try {
58 | main.plugin.getLogger().info("[Discord] Logging in...");
59 | new DiscordConnectionHelper().main();
60 | } catch (LoginException | InterruptedException e) {
61 | e.printStackTrace();
62 | }
63 | main.plugin.getLogger().info("[Discord] Reloaded!");
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/nl/corwindev/streamervschat/main.java:
--------------------------------------------------------------------------------
1 | package nl.corwindev.streamervschat;
2 |
3 | import nl.corwindev.streamervschat.command.DiscordReload;
4 | import nl.corwindev.streamervschat.command.TwitchReload;
5 | import nl.corwindev.streamervschat.command.YouTubeReload;
6 | import nl.corwindev.streamervschat.objects.UpdateChecker;
7 | import nl.corwindev.streamervschat.youtube.YouTubeConnectionHelper;
8 | import org.bstats.charts.DrilldownPie;
9 | import org.bukkit.Bukkit;
10 | import org.bukkit.plugin.java.JavaPlugin;
11 | import nl.corwindev.streamervschat.discord.DiscordConnectionHelper;
12 | import nl.corwindev.streamervschat.twitch.TwitchConnectionHelper;
13 | import javax.security.auth.login.LoginException;
14 | import nl.corwindev.streamervschat.objects.JdaFilter;
15 | import nl.corwindev.streamervschat.command.TestCommand;
16 | import org.bstats.bukkit.Metrics;
17 |
18 | import java.util.HashMap;
19 | import java.util.Map;
20 |
21 | public final class main extends JavaPlugin {
22 | // Exports this class to the plugin.
23 | public static main plugin;
24 | private JdaFilter jdaFilter;
25 |
26 | @Override
27 | public void onEnable() {
28 | this.reloadConfig();
29 | this.saveDefaultConfig();
30 | plugin = this;
31 | new UpdateChecker(this, 105119).getVersion(version -> {
32 | if (this.getDescription().getVersion().equals(version)) {
33 | getLogger().info("There is not a new update available.");
34 | } else {
35 | getLogger().warning("There is a new update available. Download it here: https://www.spigotmc.org/resources/streamer-vs-chat-1-13-1-19.105119/");
36 | }
37 | });
38 | if (!plugin.getConfig().getBoolean("twitch.enabled") && !plugin.getConfig().getBoolean("discord.enabled") && !plugin.getConfig().getBoolean("youtube.enabled")) {
39 | getLogger().info("No services enabled...");
40 | }
41 | try {
42 | commands.start();
43 | } catch (Exception e) {
44 | e.printStackTrace();
45 | }
46 | boolean serverIsLog4jCapable = false;
47 | boolean serverIsLog4j21Capable = false;
48 | try {
49 | serverIsLog4jCapable = Class.forName("org.apache.logging.log4j.core.Logger") != null;
50 | } catch (ClassNotFoundException e) {
51 | getLogger().info("Log4j classes are NOT available, console channel will not be attached");
52 | }
53 | try {
54 | serverIsLog4j21Capable = Class.forName("org.apache.logging.log4j.core.Filter") != null;
55 | } catch (ClassNotFoundException e) {
56 | getLogger().info("Log4j 2.1 classes are NOT available, JDA messages will NOT be formatted properly");
57 | }
58 |
59 | // add log4j filter for JDA messages
60 | if (serverIsLog4j21Capable && jdaFilter == null) {
61 | try {
62 | Class> jdaFilterClass = Class.forName("nl.corwindev.streamervschat.objects.JdaFilter");
63 | jdaFilter = (JdaFilter) jdaFilterClass.newInstance();
64 | ((org.apache.logging.log4j.core.Logger) org.apache.logging.log4j.LogManager.getRootLogger()).addFilter((org.apache.logging.log4j.core.Filter) jdaFilter);
65 | getLogger().info("ConsoleFilter Attached");
66 | } catch (Exception e) {
67 | e.printStackTrace();
68 | }
69 | }
70 | if (plugin.getConfig().getBoolean("twitch.enabled")) {
71 | TwitchConnectionHelper.login();
72 | }
73 | if (plugin.getConfig().getBoolean("discord.enabled")) {
74 | try {
75 | new DiscordConnectionHelper().main();
76 | } catch (LoginException | InterruptedException e) {
77 | e.printStackTrace();
78 | }
79 | }
80 | if (plugin.getConfig().getBoolean("youtube.enabled")) {
81 | YouTubeConnectionHelper.main("run");
82 | }
83 | this.getCommand("testcommand").setExecutor(new TestCommand());
84 | this.getCommand("youtube-reload").setExecutor(new YouTubeReload());
85 | this.getCommand("twitch-reload").setExecutor(new TwitchReload());
86 | this.getCommand("discord-reload").setExecutor(new DiscordReload());
87 | int pluginId = 16419;
88 | Metrics metrics = new Metrics(this, pluginId);
89 | metrics.addCustomChart(new DrilldownPie("live_platform", () -> {
90 | Map> map = new HashMap<>();
91 | Boolean YouTubeEnabled = this.getConfig().getBoolean("youtube.enabled");
92 | Boolean TwitchEnabled = this.getConfig().getBoolean("twitch.enabled");
93 | Boolean DiscordEnabled = this.getConfig().getBoolean("discord.enabled");
94 | Map entry = new HashMap<>();
95 | entry.put("YouTube", YouTubeEnabled ? 1 : 0);
96 | entry.put("Twitch", TwitchEnabled ? 1 : 0);
97 | entry.put("Discord", DiscordEnabled ? 1 : 0);
98 | if(YouTubeEnabled) {
99 | map.put("YouTube", entry);
100 | }
101 | if(TwitchEnabled) {
102 | map.put("Twitch", entry);
103 | }
104 | if(DiscordEnabled) {
105 | map.put("Discord", entry);
106 | }
107 | return map;
108 | }));
109 | }
110 |
111 | @Override
112 | public void onDisable() {
113 | if(DiscordConnectionHelper.api != null) {
114 | if (DiscordConnectionHelper.isConnected()) {
115 | DiscordConnectionHelper.api.shutdown();
116 | }
117 | }
118 | if (TwitchConnectionHelper.isConnected()) {
119 | TwitchConnectionHelper.getBot().disconnect();
120 | }
121 | YouTubeConnectionHelper.stop();
122 |
123 | getLogger().info("Corwin shutting down!");
124 |
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/main/java/nl/corwindev/streamervschat/objects/JdaFilter.java:
--------------------------------------------------------------------------------
1 | package nl.corwindev.streamervschat.objects;
2 |
3 | import org.apache.commons.lang3.exception.ExceptionUtils;
4 | import org.apache.logging.log4j.Level;
5 | import org.apache.logging.log4j.Marker;
6 | import org.apache.logging.log4j.core.Filter;
7 | import org.apache.logging.log4j.core.LogEvent;
8 | import org.apache.logging.log4j.core.Logger;
9 | import org.apache.logging.log4j.message.Message;
10 | import nl.corwindev.streamervschat.main;
11 |
12 |
13 | public class JdaFilter implements Filter {
14 |
15 | public Result check(String loggerName, Level level, String message, Throwable throwable) {
16 | if (loggerName.startsWith("net.dv8tion")) {
17 |
18 | switch (level.name()) {
19 | case "INFO":
20 | main.plugin.getLogger().info("[JDA] " + message);
21 | break;
22 | case "WARN":
23 | if (message.contains("Encountered 429")) {
24 | main.plugin.getLogger().info(message);
25 | break;
26 | }
27 |
28 | main.plugin.getLogger().warning("[JDA] " + message);
29 | break;
30 | case "ERROR":
31 | if (message.contains("Requester timed out while executing a request")) {
32 | main.plugin.getLogger().log(java.util.logging.Level.WARNING,"[JDA] " + message + ". This is either a issue on Discord's end (https://discordstatus.com) or with your server's connection");
33 |
34 | main.plugin.getLogger().log(java.util.logging.Level.WARNING, ExceptionUtils.getStackTrace(throwable));
35 | break;
36 | }
37 |
38 | if (throwable != null) {
39 | main.plugin.getLogger().info("[JDA] " + message + "\n" + ExceptionUtils.getStackTrace(throwable));
40 | } else {
41 | main.plugin.getLogger().info("[JDA] " + message);
42 | }
43 | break;
44 | default:
45 | main.plugin.getLogger().info("[JDA] " + message);
46 | }
47 | }else if(loggerName.startsWith("com.github.twitch4j") || loggerName.startsWith("com.github.philippheuer.events4j")) {
48 | switch (level.name()) {
49 | case "INFO":
50 | main.plugin.getLogger().info("[TWITCH] " + message);
51 | break;
52 | case "WARN":
53 | main.plugin.getLogger().warning("[TWITCH] " + message);
54 | break;
55 | case "ERROR":
56 | if (throwable != null) {
57 | main.plugin.getLogger().info("[TWITCH] " + message + "\n" + ExceptionUtils.getStackTrace(throwable));
58 | } else {
59 | main.plugin.getLogger().info("[TWITCH] " + message);
60 | }
61 | break;
62 | default:
63 | main.plugin.getLogger().info("[TWITCH] " + message);
64 | }
65 | }else if(loggerName.startsWith("com.google.api")){
66 | switch (level.name()) {
67 | case "INFO":
68 | main.plugin.getLogger().info("[YOUTUBE] " + message);
69 | break;
70 | case "WARN":
71 | main.plugin.getLogger().warning("[YOUTUBE] " + message);
72 | break;
73 | case "ERROR":
74 | if (throwable != null) {
75 | main.plugin.getLogger().info("[YOUTUBE] " + message + "\n" + ExceptionUtils.getStackTrace(throwable));
76 | } else {
77 | main.plugin.getLogger().info("[YOUTUBE] " + message);
78 | }
79 | break;
80 | default:
81 | main.plugin.getLogger().info("[YOUTUBE] " + message);
82 | }
83 | }else{
84 | return Result.NEUTRAL;
85 | }
86 | return Result.DENY;
87 |
88 | }
89 |
90 | @Override
91 | public Result filter(LogEvent logEvent) {
92 | return check(
93 | logEvent.getLoggerName(),
94 | logEvent.getLevel(),
95 | logEvent.getMessage()
96 | .getFormattedMessage(),
97 | logEvent.getThrown());
98 | }
99 | @Override
100 | public Result filter(Logger logger, Level level, Marker marker, String message, Object... parameters) {
101 | return check(
102 | logger.getName(),
103 | level,
104 | message,
105 | null);
106 | }
107 |
108 | @Override
109 | public Result filter(Logger logger, Level level, Marker marker, String message, Object p0) {
110 | return null;
111 | }
112 |
113 | @Override
114 | public Result filter(Logger logger, Level level, Marker marker, String message, Object p0, Object p1) {
115 | return null;
116 | }
117 |
118 | @Override
119 | public Result filter(Logger logger, Level level, Marker marker, String message, Object p0, Object p1, Object p2) {
120 | return null;
121 | }
122 |
123 | @Override
124 | public Result filter(Logger logger, Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3) {
125 | return null;
126 | }
127 |
128 | @Override
129 | public Result filter(Logger logger, Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4) {
130 | return null;
131 | }
132 |
133 | @Override
134 | public Result filter(Logger logger, Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {
135 | return null;
136 | }
137 |
138 | @Override
139 | public Result filter(Logger logger, Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {
140 | return null;
141 | }
142 |
143 | @Override
144 | public Result filter(Logger logger, Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {
145 | return null;
146 | }
147 |
148 | @Override
149 | public Result filter(Logger logger, Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {
150 | return null;
151 | }
152 |
153 | @Override
154 | public Result filter(Logger logger, Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {
155 | return null;
156 | }
157 |
158 | @Override
159 | public Result filter(Logger logger, Level level, Marker marker, Object message, Throwable throwable) {
160 | return check(
161 | logger.getName(),
162 | level,
163 | message.toString(),
164 | throwable);
165 | }
166 | @Override
167 | public Result filter(Logger logger, Level level, Marker marker, Message message, Throwable throwable) {
168 | return check(
169 | logger.getName(),
170 | level,
171 | message.getFormattedMessage(),
172 | throwable);
173 | }
174 |
175 | @Override
176 | public State getState() {
177 | return null;
178 | }
179 |
180 | @Override
181 | public void initialize() {
182 |
183 | }
184 |
185 | public void start() {}
186 | public void stop() {}
187 | public boolean isStarted() {
188 | return true;
189 | }
190 | public boolean isStopped() {
191 | return false;
192 | }
193 |
194 | @Override
195 | public Result getOnMismatch() {
196 | return Result.NEUTRAL;
197 | }
198 | @Override
199 | public Result getOnMatch() {
200 | return Result.NEUTRAL;
201 | }
202 | }
--------------------------------------------------------------------------------
/src/main/java/nl/corwindev/streamervschat/objects/UpdateChecker.java:
--------------------------------------------------------------------------------
1 | package nl.corwindev.streamervschat.objects;
2 |
3 | import org.bukkit.Bukkit;
4 | import org.bukkit.plugin.java.JavaPlugin;
5 |
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.net.URL;
9 | import java.util.Scanner;
10 | import java.util.function.Consumer;
11 |
12 | public class UpdateChecker {
13 |
14 | private final JavaPlugin plugin;
15 | private final int resourceId;
16 |
17 | public UpdateChecker(JavaPlugin plugin, int resourceId) {
18 | this.plugin = plugin;
19 | this.resourceId = resourceId;
20 | }
21 |
22 | public void getVersion(final Consumer consumer) {
23 | Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> {
24 | try (InputStream inputStream = new URL("https://api.spigotmc.org/legacy/update.php?resource=" + this.resourceId).openStream(); Scanner scanner = new Scanner(inputStream)) {
25 | if (scanner.hasNext()) {
26 | consumer.accept(scanner.next());
27 | }
28 | } catch (IOException exception) {
29 | plugin.getLogger().info("Unable to check for updates: " + exception.getMessage());
30 | }
31 | });
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/nl/corwindev/streamervschat/twitch/TwitchConnectionHelper.java:
--------------------------------------------------------------------------------
1 | package nl.corwindev.streamervschat.twitch;
2 |
3 |
4 | import com.github.philippheuer.credentialmanager.domain.OAuth2Credential;
5 | import com.github.philippheuer.events4j.simple.SimpleEventHandler;
6 | import com.github.twitch4j.chat.TwitchChat;
7 | import com.github.twitch4j.chat.TwitchChatBuilder;
8 | import com.github.twitch4j.chat.enums.TMIConnectionState;
9 | import nl.corwindev.streamervschat.main;
10 |
11 | import java.util.function.Supplier;
12 |
13 | import static nl.corwindev.streamervschat.main.plugin;
14 |
15 | public class TwitchConnectionHelper {
16 | private static Thread botThread = null;
17 | private static TwitchChat twitchClient = null;
18 |
19 | public static TwitchChat getBot() {
20 | return twitchClient;
21 | }
22 | public static boolean login() {
23 | try {
24 | OAuth2Credential credential = new OAuth2Credential("twitch", plugin.getConfig().getString("twitch.token"));
25 | twitchClient = TwitchChatBuilder.builder()
26 | .withChatAccount(credential)
27 | .withDefaultEventHandler(SimpleEventHandler.class)
28 | .build();
29 |
30 |
31 | botThread = new Thread(() -> {
32 | TwitchEvents bot = new TwitchEvents(twitchClient.getEventManager().getEventHandler(SimpleEventHandler.class));
33 | twitchClient.joinChannel(plugin.getConfig().getString("twitch.channel"));
34 | twitchClient.connect();
35 | });
36 |
37 | botThread.start();
38 | return true;
39 |
40 | } catch (Exception e) {
41 | // Log logger to console
42 |
43 | plugin.getLogger().warning((Supplier) e);
44 | return false;
45 | }
46 | }
47 | public static boolean isConnected() {
48 |
49 | if (twitchClient != null) {
50 | return twitchClient.getConnectionState().equals(TMIConnectionState.CONNECTED);
51 | } else {
52 | return false;
53 | }
54 |
55 | }
56 |
57 | public static void disconnectBot() {
58 |
59 | twitchClient.disconnect();
60 | botThread.interrupt();
61 |
62 | plugin.getLogger().info("Shutted down twitch bot");
63 | }
64 |
65 | public static void reload(){
66 | main.plugin.getLogger().info("[Twitch] Reloading...");
67 | main.plugin.reloadConfig();
68 | if(isConnected()){
69 | disconnectBot();
70 | }
71 | main.plugin.getLogger().info("[Twitch] Reloaded!");
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/nl/corwindev/streamervschat/twitch/TwitchEvents.java:
--------------------------------------------------------------------------------
1 | package nl.corwindev.streamervschat.twitch;
2 |
3 | import com.github.philippheuer.events4j.simple.SimpleEventHandler;
4 | import com.github.twitch4j.chat.events.channel.ChannelMessageEvent;
5 | import nl.corwindev.streamervschat.commands;
6 | import nl.corwindev.streamervschat.main;
7 |
8 | public class TwitchEvents {
9 |
10 | public TwitchEvents(SimpleEventHandler eventHandler) {
11 |
12 | eventHandler.onEvent(ChannelMessageEvent.class, this::onChannelMessage);
13 | }
14 |
15 | private void onChannelMessage(ChannelMessageEvent event) {
16 | System.out.println(event.getUser().getName() + ": " + event.getMessage());
17 | if (event.getMessage().contains(main.plugin.getConfig().getString("commands.prefix"))) {
18 | commands.UserList.add(event.getUser().getName());
19 | commands.commandList.add(event.getMessage().replace(main.plugin.getConfig().getString("commands.prefix"), ""));
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/java/nl/corwindev/streamervschat/youtube/YouTubeConnectionHelper.java:
--------------------------------------------------------------------------------
1 | package nl.corwindev.streamervschat.youtube;
2 |
3 |
4 | import com.google.api.client.http.HttpRequestInitializer;
5 | import com.google.api.client.http.javanet.NetHttpTransport;
6 | import com.google.api.client.json.jackson2.JacksonFactory;
7 |
8 | import com.google.api.client.util.DateTime;
9 | import com.google.api.services.youtube.YouTube;
10 | import com.google.api.services.youtube.model.*;
11 | import nl.corwindev.streamervschat.commands;
12 | import nl.corwindev.streamervschat.main;
13 |
14 | import java.util.*;
15 |
16 |
17 | public class YouTubeConnectionHelper {
18 | private static final String LIVE_CHAT_FIELDS =
19 | "items(authorDetails(channelId,displayName,isChatModerator,isChatOwner,isChatSponsor,"
20 | + "profileImageUrl),snippet(displayMessage,superChatDetails,publishedAt)),"
21 | + "nextPageToken,pollingIntervalMillis";
22 | public static boolean started = false;
23 | private static YouTube youtube;
24 | public static void main(String args) {
25 |
26 | // This OAuth 2.0 access scope allows for read-only access to the
27 | // authenticated user's account, but not other types of account access.
28 |
29 | try {
30 | String liveChatId = main.plugin.getConfig().getString("youtube.youtubeId");
31 | NetHttpTransport transport = new NetHttpTransport.Builder().build();
32 | JacksonFactory jsonFactory = JacksonFactory.getDefaultInstance();
33 | HttpRequestInitializer httpRequestInitializer = request -> {
34 | request.setInterceptor(intercepted -> intercepted.getUrl().set("key", main.plugin.getConfig().getString("youtube.apiKey")));
35 | };
36 |
37 | youtube = new YouTube.Builder(transport, jsonFactory, httpRequestInitializer)
38 | .setApplicationName("StreamerVsChat")
39 | .build();
40 |
41 | liveChatId = youtube.videos().list("liveStreamingDetails").setId(liveChatId).execute().getItems().get(0).getLiveStreamingDetails().getActiveLiveChatId();
42 | listChatMessages(liveChatId, null, main.plugin.getConfig().getInt("commands.delay") * 1000);
43 | } catch (Throwable t) {
44 | main.plugin.getLogger().warning("[YouTube] Error: " + t.getMessage());
45 | }
46 | }
47 | public static TimerTask tt = null;
48 | /**
49 | * Lists live chat messages, polling at the server supplied interval. Owners and moderators of a
50 | * live chat will poll at a faster rate.
51 | *
52 | * @param liveChatId The live chat id to list messages from.
53 | * @param nextPageToken The page token from the previous request, if any.
54 | * @param delayMs The delay in milliseconds before making the request.
55 | */
56 | private static void listChatMessages(
57 | final String liveChatId,
58 | final String nextPageToken,
59 | long delayMs) {
60 | Timer pollTimer = new Timer();
61 | pollTimer.schedule(
62 | new TimerTask() {
63 | @Override
64 | public void run() {
65 | tt = this;
66 | try {
67 | // Get chat messages from YouTube
68 | LiveChatMessageListResponse response = youtube
69 | .liveChatMessages()
70 | .list(liveChatId, "snippet, authorDetails")
71 | .setPageToken(nextPageToken)
72 | .setFields(LIVE_CHAT_FIELDS)
73 | .execute();
74 |
75 | // Display messages and super chat details
76 | List messages = response.getItems();
77 | // Skip first run
78 | for (int i = 0; i < messages.size(); i++) {
79 | LiveChatMessage message = messages.get(i);
80 | LiveChatMessageSnippet snippet = message.getSnippet();
81 | buildOutput(
82 | snippet.getDisplayMessage(),
83 | message.getAuthorDetails(),
84 | snippet.getSuperChatDetails(),
85 | snippet.getPublishedAt());
86 | }
87 |
88 | // Request the next page of messages
89 | listChatMessages(
90 | liveChatId,
91 | response.getNextPageToken(),
92 | response.getPollingIntervalMillis());
93 |
94 | } catch (Throwable t) {
95 | main.plugin.getLogger().warning("[YouTube] Error: " + t.getMessage());
96 | }
97 | }
98 | }, main.plugin.getConfig().getInt("commands.delay") * 1000);
99 | }
100 |
101 | /**
102 | * Formats a chat message for console output.
103 | *
104 | * @param message The display message to output.
105 | * @param author The author of the message.
106 | * @param superChatDetails SuperChat details associated with the message.
107 | * @return A formatted string for console output.
108 | */
109 | private static String buildOutput(
110 | String message,
111 | LiveChatMessageAuthorDetails author,
112 | LiveChatSuperChatDetails superChatDetails,
113 | DateTime publishedAt) {
114 | // Check if message is older then 5 minutes
115 | if (publishedAt.getValue() < System.currentTimeMillis() - (main.plugin.getConfig().getInt("commands.delay") * 1000 + 1000)) {
116 | return "";
117 | }
118 | StringBuilder output = new StringBuilder();
119 | if (superChatDetails != null) {
120 | output.append(superChatDetails.getAmountDisplayString());
121 | output.append("SUPERCHAT RECEIVED FROM ");
122 | commands.runCmd(message.replace(main.plugin.getConfig().getString("commands.prefix"), ""), author.getDisplayName());
123 | }
124 | output.append(author.getDisplayName());
125 | List roles = new ArrayList();
126 | if (author.getIsChatOwner()) {
127 | roles.add("OWNER");
128 | }
129 | if (author.getIsChatModerator()) {
130 | roles.add("MODERATOR");
131 | }
132 | if (author.getIsChatSponsor()) {
133 | roles.add("SPONSOR");
134 | }
135 | if (roles.size() > 0) {
136 | output.append(" (");
137 | String delim = "";
138 | for (String role : roles) {
139 | output.append(delim).append(role);
140 | delim = ", ";
141 | }
142 | output.append(")");
143 | }
144 | if (message != null && !message.isEmpty()) {
145 | output.append(": ");
146 | output.append(message);
147 | }
148 | if (message.contains(main.plugin.getConfig().getString("commands.prefix"))) {
149 | commands.UserList.add(author.getDisplayName());
150 | commands.commandList.add(message.replace(main.plugin.getConfig().getString("commands.prefix"), ""));
151 | }else{
152 | main.plugin.getServer().broadcastMessage(output.toString());
153 | }
154 | return output.toString();
155 | }
156 |
157 | public static void reload(){
158 | main.plugin.getLogger().info("[YouTube] Reloading...");
159 | main.plugin.reloadConfig();
160 | if(tt != null){
161 | tt.cancel();
162 | }
163 | main("run");
164 | main.plugin.getLogger().info("[YouTube] Reloaded!");
165 | }
166 |
167 | public static void stop(){
168 | main.plugin.getLogger().info("[YouTube] Stopping...");
169 | if(tt != null){
170 | tt.cancel();
171 | }
172 | main.plugin.getLogger().info("[YouTube] Stopped!");
173 | }
174 | }
--------------------------------------------------------------------------------
/src/main/resources/config.yml:
--------------------------------------------------------------------------------
1 | # Commands Prefix
2 | # Delay between commands
3 | # Its recommended to set this to 10 seconds or higher
4 |
5 | commands: {
6 | prefix: '!',
7 | delay: 30
8 | }
9 |
10 | # Set affected players
11 | # all/permission
12 | # all: All players will be affected
13 | # permission: Only players with the permission (nl.corwindev.streamervschat.streamer) will be affected
14 | affected-players: all
15 |
16 | # Poison effect
17 | # Set the duration of the poison effect
18 | poison-duration: 20
19 |
20 | # Blacklist
21 | # Set the words that will be blacklisted
22 | # If a player says one of these words, he will be denied
23 | blacklist: []
24 |
25 | # Cooldown
26 | # Set the cooldown for the commands
27 | # If a player uses a command, he will be denied for the set amount of seconds
28 | cooldowns:
29 | dropall: 30
30 | drop: 30
31 |
32 |
33 | # Hotbar message
34 | # Set the message that will be displayed in the hotbar
35 | # %player% will be replaced with the player's name
36 | # %command% will be replaced with the command
37 | hotbar: '§a§l%user%§r§a has executed the command: §l%command%'
38 |
39 |
40 | # Discord Bot
41 | # https://github.com/CorwinDev/StreamerVSChat/wiki#discord-setup
42 | discord: {
43 | enabled: false,
44 | token: 'discord token',
45 | channel: 'channel id'
46 | }
47 |
48 | # Twitch Chat
49 | # https://github.com/CorwinDev/StreamerVSChat/wiki#twitch-setup
50 | twitch: {
51 | enabled: false,
52 | token: 'twitch token',
53 | channel: 'twitch channel'
54 | }
55 |
56 | # Youtube Chat
57 | # https://github.com/CorwinDev/StreamerVSChat/wiki#youtube-setup
58 | youtube: {
59 | enabled: false,
60 | youtubeId: 'youtube id',
61 | apiKey: 'youtube api key'
62 | }
63 |
64 | # Custom Commands
65 | #
66 | # You can add custom commands to the plugin
67 | # You can add as many commands as you want
68 | # Command name without the prefix
69 | # Command: Command that will be executed without the /
70 | # You can use %player% to get the player name
71 | # Example: !test -> /give %player% diamond 1
72 |
73 | customcommands:
74 | 'test':
75 | command: 'give %player% diamond 1'
76 | cooldown: 30
77 | 'test2':
78 | command: 'give %player% diamond 2'
--------------------------------------------------------------------------------
/src/main/resources/plugin.yml:
--------------------------------------------------------------------------------
1 | name: StreamerVsChat
2 | version: '2.2'
3 | main: nl.corwindev.streamervschat.main
4 | api-version: 1.13
5 | commands:
6 | testcommand:
7 | description: 'Test the commands'
8 | usage: '/testcommand'
9 | permission: nl.corwindev.streamervschat.streamer
10 | permission-message: 'You do not have permission to use this command'
11 | default: false
12 | permission-default: op
13 | youtube-reload:
14 | description: 'Reload youtube integration'
15 | usage: '/yt-reload'
16 | permission: nl.corwindev.streamervschat.streamer
17 | permission-message: 'You do not have permission to use this command'
18 | default: false
19 | permission-default: op
20 | twitch-reload:
21 | description: 'Reload twitch integration'
22 | usage: '/twitch-reload'
23 | permission: nl.corwindev.streamervschat.streamer
24 | permission-message: 'You do not have permission to use this command'
25 | default: false
26 | permission-default: op
27 | discord-reload:
28 | description: 'Reload Discord integration'
29 | usage: '/discord-reload'
30 | permission: nl.corwindev.streamervschat.streamer
31 | permission-message: 'You do not have permission to use this command'
32 | default: false
33 | permission-default: op
34 |
--------------------------------------------------------------------------------