done i think
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/target
|
97
pom.xml
97
pom.xml
@@ -0,0 +1,97 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.minster586</groupId>
|
||||
<artifactId>tiktok-stream-plugin</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>TikTokStreamPlugin</name>
|
||||
<description>Integrates TikTok Live events with Minecraft 1.19</description>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spigot API for Minecraft 1.19 -->
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.19-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Java-WebSocket for TikTok stream events -->
|
||||
<dependency>
|
||||
<groupId>org.java-websocket</groupId>
|
||||
<artifactId>Java-WebSocket</artifactId>
|
||||
<version>1.5.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Gson for JSON parsing -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.10.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- SnakeYAML for YAML parsing -->
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>2.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
<!-- Spigot repo for 1.19 snapshot -->
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Compiler plugin -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Shade plugin to bundle dependencies -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals><goal>shade</goal></goals>
|
||||
<configuration>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.java_websocket</pattern>
|
||||
<shadedPattern>com.minster586.shaded.websocket</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
102
src/main/java/com/minster586/events/TikTokEventDispatcher.java
Normal file
102
src/main/java/com/minster586/events/TikTokEventDispatcher.java
Normal file
@@ -0,0 +1,102 @@
|
||||
package com.minster586.tiktokstream.events;
|
||||
|
||||
import com.minster586.tiktokstream.TikTokStreamPlugin;
|
||||
import com.minster586.tiktokstream.config.ConfigManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import com.minster586.ui.NotificationManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TikTokEventDispatcher {
|
||||
|
||||
private final ConfigManager config;
|
||||
|
||||
public TikTokEventDispatcher() {
|
||||
this.config = TikTokStreamPlugin.getInstance().getConfigManager();
|
||||
}
|
||||
|
||||
public void handleGift(String username, String giftName, int amount) {
|
||||
if (!config.isGiftEnabled()) return;
|
||||
|
||||
List<String> locations = config.getGiftLocations();
|
||||
String prefix = config.getPrefix();
|
||||
|
||||
String chatMessage = config.getGiftChatMessage()
|
||||
.replace("%prefix%", prefix)
|
||||
.replace("%username%", username)
|
||||
.replace("%giftName%", giftName)
|
||||
.replace("%amount%", String.valueOf(amount));
|
||||
|
||||
String actionBarMessage = config.getGiftActionBarMessage()
|
||||
.replace("%prefix%", prefix)
|
||||
.replace("%username%", username)
|
||||
.replace("%giftName%", giftName)
|
||||
.replace("%amount%", String.valueOf(amount));
|
||||
|
||||
if (locations.contains("chat")) {
|
||||
Bukkit.broadcastMessage(chatMessage);
|
||||
}
|
||||
|
||||
if (locations.contains("action-bar")) {
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(actionBarMessage));
|
||||
}
|
||||
}
|
||||
|
||||
// Toast notifications removed. Use NotificationManager for chat/action-bar only.
|
||||
}
|
||||
|
||||
public void handleJoin(String username) {
|
||||
if (!config.isJoinEnabled()) return;
|
||||
|
||||
String location = config.getJoinLocation();
|
||||
String message = config.getJoinActionBarMessage().replace("%username%", username);
|
||||
|
||||
switch (location) {
|
||||
case "chat" -> Bukkit.broadcastMessage(config.getJoinChatMessage().replace("%username%", username));
|
||||
case "action-bar" -> Bukkit.getOnlinePlayers().forEach(p -> p.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(message)));
|
||||
// Toast notifications removed
|
||||
}
|
||||
}
|
||||
|
||||
public void handleChat(String username, String messageText) {
|
||||
if (!config.isChatEnabled()) return;
|
||||
|
||||
String location = config.getChatLocation();
|
||||
String formatted = config.getChatMessage()
|
||||
.replace("%prefix%", config.getPrefix())
|
||||
.replace("%username%", username)
|
||||
.replace("%message%", messageText);
|
||||
|
||||
switch (location) {
|
||||
case "chat" -> Bukkit.broadcastMessage(formatted);
|
||||
case "action-bar" -> Bukkit.getOnlinePlayers().forEach(p -> p.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(
|
||||
config.getChatActionBarMessage()
|
||||
.replace("%username%", username)
|
||||
.replace("%message%", messageText)
|
||||
)));
|
||||
// Toast notifications removed
|
||||
}
|
||||
}
|
||||
|
||||
public void handleFollow(String username) {
|
||||
if (!config.isFollowEnabled()) return;
|
||||
|
||||
List<String> locations = config.getFollowLocations();
|
||||
|
||||
if (locations.contains("chat")) {
|
||||
Bukkit.broadcastMessage(config.getFollowChatMessage().replace("%username%", username));
|
||||
}
|
||||
|
||||
if (locations.contains("action-bar")) {
|
||||
Bukkit.getOnlinePlayers().forEach(p -> p.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(
|
||||
config.getFollowActionBarMessage().replace("%username%", username)
|
||||
)));
|
||||
}
|
||||
|
||||
// Toast notifications removed. Use NotificationManager for chat/action-bar only.
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
package com.minster586.tiktokstream;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class TikTokLiveCommand implements CommandExecutor, TabCompleter {
|
||||
private final TikTokStreamPlugin plugin;
|
||||
private static final String PERMISSION = "tiktok.live";
|
||||
|
||||
public TikTokLiveCommand(TikTokStreamPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!sender.hasPermission(PERMISSION)) {
|
||||
sender.sendMessage(ChatColor.RED + "You do not have permission to use this command.");
|
||||
return true;
|
||||
}
|
||||
if (args.length != 1 || !(args[0].equalsIgnoreCase("enable") || args[0].equalsIgnoreCase("disable"))) {
|
||||
sender.sendMessage(ChatColor.YELLOW + "Usage: /tiktok live <enable|disable>");
|
||||
return true;
|
||||
}
|
||||
boolean enable = args[0].equalsIgnoreCase("enable");
|
||||
plugin.setTiktokLiveEnabled(enable);
|
||||
sender.sendMessage(ChatColor.GREEN + "TikTok live notifications " + (enable ? "enabled" : "disabled") + ".");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
||||
if (args.length == 1) {
|
||||
return Arrays.asList("enable", "disable");
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
@@ -2,15 +2,18 @@ package com.minster586.tiktokstream;
|
||||
|
||||
import com.minster586.tiktokstream.config.ConfigManager;
|
||||
import com.minster586.tiktokstream.websocket.StreamerBotWebSocketClient;
|
||||
import com.minster586.tiktokstream.util.GiftMappingManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
public class TikTokStreamPlugin extends JavaPlugin {
|
||||
|
||||
public class TikTokStreamPlugin extends JavaPlugin {
|
||||
private static TikTokStreamPlugin instance;
|
||||
private ConfigManager configManager;
|
||||
private StreamerBotWebSocketClient webSocketClient;
|
||||
private GiftMappingManager giftMappingManager;
|
||||
private boolean tiktokLiveEnabled = true;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
@@ -20,12 +23,31 @@ public class TikTokStreamPlugin extends JavaPlugin {
|
||||
configManager = new ConfigManager(this);
|
||||
configManager.load();
|
||||
|
||||
// Initialize GiftMappingManager
|
||||
String giftMappingUrl = getConfig().getString("config.giftMappingUrl");
|
||||
if (giftMappingUrl != null && !giftMappingUrl.isEmpty()) {
|
||||
giftMappingManager = new GiftMappingManager(this, giftMappingUrl);
|
||||
} else {
|
||||
getLogger().warning("No giftMappingUrl found in config! Gift names will not be available.");
|
||||
}
|
||||
|
||||
String websocketUrl = configManager.getWebSocketUrl();
|
||||
webSocketClient = new StreamerBotWebSocketClient(URI.create(websocketUrl));
|
||||
webSocketClient.connect();
|
||||
|
||||
// Register /tiktok live command
|
||||
getCommand("tiktok").setExecutor(new TikTokLiveCommand(this));
|
||||
getCommand("tiktok").setTabCompleter(new TikTokLiveCommand(this));
|
||||
|
||||
getLogger().info("TikTokStreamPlugin enabled and connected to Streamer.bot.");
|
||||
}
|
||||
public boolean isTiktokLiveEnabled() {
|
||||
return tiktokLiveEnabled;
|
||||
}
|
||||
|
||||
public void setTiktokLiveEnabled(boolean enabled) {
|
||||
this.tiktokLiveEnabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
@@ -42,4 +64,8 @@ public class TikTokStreamPlugin extends JavaPlugin {
|
||||
public ConfigManager getConfigManager() {
|
||||
return configManager;
|
||||
}
|
||||
|
||||
public GiftMappingManager getGiftMappingManager() {
|
||||
return giftMappingManager;
|
||||
}
|
||||
}
|
@@ -0,0 +1,150 @@
|
||||
package com.minster586.tiktokstream.config;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.*;
|
||||
|
||||
public class ConfigManager {
|
||||
|
||||
private final JavaPlugin plugin;
|
||||
private FileConfiguration config;
|
||||
|
||||
public ConfigManager(JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void load() {
|
||||
File configFile = new File(plugin.getDataFolder(), "config.yml");
|
||||
|
||||
if (!configFile.exists()) {
|
||||
plugin.saveResource("config.yml", false);
|
||||
}
|
||||
|
||||
config = YamlConfiguration.loadConfiguration(configFile);
|
||||
|
||||
// Load defaults from resources/config.yml
|
||||
InputStream defaultStream = plugin.getResource("config.yml");
|
||||
if (defaultStream != null) {
|
||||
YamlConfiguration defaultConfig = YamlConfiguration.loadConfiguration(new InputStreamReader(defaultStream));
|
||||
config.setDefaults(defaultConfig);
|
||||
}
|
||||
}
|
||||
|
||||
// 🔧 Accessors (no hardcoded defaults — rely on config.yml)
|
||||
public String getPrefix() {
|
||||
return config.getString("config.prefix");
|
||||
}
|
||||
|
||||
public String getTikTokUsername() {
|
||||
return config.getString("config.tiktok_username");
|
||||
}
|
||||
|
||||
public String getGiftMappingUrl() {
|
||||
return config.getString("config.giftMappingUrl");
|
||||
}
|
||||
|
||||
|
||||
public String getWebSocketUrl() {
|
||||
return config.getString("config.websocket.url");
|
||||
}
|
||||
|
||||
|
||||
public int getWebSocketRefreshDelay() {
|
||||
return config.getInt("config.websocket.refresh-delay");
|
||||
}
|
||||
|
||||
public boolean isJoinEnabled() {
|
||||
return config.getBoolean("config.settings.join.joined-enabled");
|
||||
}
|
||||
|
||||
public String getJoinLocation() {
|
||||
return config.getString("config.settings.join.loctions");
|
||||
}
|
||||
|
||||
public String getJoinChatMessage() {
|
||||
return config.getString("config.settings.join.chat-message");
|
||||
}
|
||||
|
||||
public String getJoinActionBarMessage() {
|
||||
return config.getString("config.settings.join.action-bar-message");
|
||||
}
|
||||
|
||||
public boolean isGiftEnabled() {
|
||||
return config.getBoolean("config.settings.gift.gifts-enabled");
|
||||
}
|
||||
|
||||
public List<String> getGiftLocations() {
|
||||
return parseLocationList("config.settings.gift.loctions");
|
||||
}
|
||||
|
||||
public String getGiftChatMessage() {
|
||||
return config.getString("config.settings.gift.chat-message");
|
||||
}
|
||||
|
||||
public String getGiftActionBarMessage() {
|
||||
return config.getString("config.settings.gift.action-bar-message");
|
||||
}
|
||||
|
||||
public boolean isChatEnabled() {
|
||||
return config.getBoolean("config.settings.chat.chat-enabled");
|
||||
}
|
||||
|
||||
public String getChatLocation() {
|
||||
return config.getString("config.settings.chat.loctions");
|
||||
}
|
||||
|
||||
public String getChatMessage() {
|
||||
return config.getString("config.settings.chat.chat-message");
|
||||
}
|
||||
|
||||
public String getChatActionBarMessage() {
|
||||
return config.getString("config.settings.chat.action-bar-message");
|
||||
}
|
||||
|
||||
|
||||
public boolean isFollowEnabled() {
|
||||
return config.getBoolean("config.settings.follows.follow-enabled");
|
||||
}
|
||||
|
||||
public List<String> getFollowLocations() {
|
||||
return parseLocationList("config.settings.follows.loctions");
|
||||
}
|
||||
|
||||
public String getFollowChatMessage() {
|
||||
return config.getString("config.settings.follows.chat-message");
|
||||
}
|
||||
|
||||
public String getFollowActionBarMessage() {
|
||||
return config.getString("config.settings.follows.action-bar-message");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 🔧 Helpers
|
||||
private List<String> parseLocationList(String path) {
|
||||
String raw = config.getString(path);
|
||||
if (raw == null) return Collections.emptyList();
|
||||
return Arrays.stream(raw.split(","))
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isEmpty())
|
||||
.toList();
|
||||
}
|
||||
|
||||
private Integer getNullableInt(String path) {
|
||||
if (!config.contains(path) || config.get(path) == null) return null;
|
||||
return config.getInt(path);
|
||||
}
|
||||
// Generic config accessors for plugin internals
|
||||
public int getIntOrDefault(String path, int def) {
|
||||
if (!config.contains(path) || config.get(path) == null) return def;
|
||||
return config.getInt(path);
|
||||
}
|
||||
|
||||
public String getStringOrDefault(String path, String def) {
|
||||
if (!config.contains(path) || config.get(path) == null) return def;
|
||||
return config.getString(path);
|
||||
}
|
||||
}
|
@@ -0,0 +1,94 @@
|
||||
package com.minster586.tiktokstream.util;
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
public class GiftMappingManager {
|
||||
private final JavaPlugin plugin;
|
||||
private final File mappingFile;
|
||||
private Map<Integer, String> giftMap = new HashMap<>();
|
||||
|
||||
public GiftMappingManager(JavaPlugin plugin, String mappingUrl) {
|
||||
this.plugin = plugin;
|
||||
this.mappingFile = new File(plugin.getDataFolder(), "gift-mapping.yaml");
|
||||
checkAndUpdateMapping(mappingUrl);
|
||||
loadMapping();
|
||||
}
|
||||
|
||||
private void checkAndUpdateMapping(String urlStr) {
|
||||
try {
|
||||
// Download remote file to temp
|
||||
File tempFile = File.createTempFile("gift-mapping", ".yaml");
|
||||
try (InputStream in = new URL(urlStr).openStream();
|
||||
FileOutputStream out = new FileOutputStream(tempFile)) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
// Compare contents
|
||||
boolean shouldReplace = !mappingFile.exists() || !filesEqual(mappingFile, tempFile);
|
||||
if (shouldReplace) {
|
||||
try (InputStream in = new FileInputStream(tempFile);
|
||||
OutputStream out = new FileOutputStream(mappingFile)) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
plugin.getLogger().info("Gift mapping updated from remote.");
|
||||
} else {
|
||||
plugin.getLogger().info("Gift mapping is up to date.");
|
||||
}
|
||||
tempFile.delete();
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().warning("Failed to check/update gift mapping: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean filesEqual(File f1, File f2) throws IOException {
|
||||
if (f1.length() != f2.length()) return false;
|
||||
try (InputStream in1 = new FileInputStream(f1); InputStream in2 = new FileInputStream(f2)) {
|
||||
int b1, b2;
|
||||
do {
|
||||
b1 = in1.read();
|
||||
b2 = in2.read();
|
||||
if (b1 != b2) return false;
|
||||
} while (b1 != -1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// downloadMapping is now handled by checkAndUpdateMapping
|
||||
|
||||
public void loadMapping() {
|
||||
if (!mappingFile.exists()) return;
|
||||
try (InputStream input = new FileInputStream(mappingFile)) {
|
||||
Yaml yaml = new Yaml();
|
||||
Map<String, Object> data = yaml.load(input);
|
||||
giftMap.clear();
|
||||
if (data != null) {
|
||||
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
||||
try {
|
||||
int id = Integer.parseInt(entry.getKey());
|
||||
giftMap.put(id, String.valueOf(entry.getValue()));
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().warning("Failed to load gift mapping: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public String getGiftName(int id) {
|
||||
return giftMap.getOrDefault(id, "Unknown Gift");
|
||||
}
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
package com.minster586.tiktokstream.websocket;
|
||||
|
||||
|
||||
import org.java_websocket.client.WebSocketClient;
|
||||
import org.java_websocket.handshake.ServerHandshake;
|
||||
import java.net.URI;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import com.minster586.tiktokstream.TikTokStreamPlugin;
|
||||
import com.minster586.tiktokstream.config.ConfigManager;
|
||||
|
||||
public class StreamerBotWebSocketClient extends WebSocketClient {
|
||||
private int retryCount = 0;
|
||||
private final ConfigManager configManager;
|
||||
private final int maxRetries;
|
||||
private final String notifyPermission;
|
||||
private final String notifyMessage;
|
||||
|
||||
public StreamerBotWebSocketClient(URI serverUri) {
|
||||
super(serverUri);
|
||||
this.configManager = TikTokStreamPlugin.getInstance().getConfigManager();
|
||||
this.maxRetries = configManager != null ? configManager.getIntOrDefault("config.websocket.retry-count", 3) : 3;
|
||||
this.notifyPermission = configManager != null ? configManager.getStringOrDefault("config.websocket.notify-permission", "tiktok.live") : "tiktok.live";
|
||||
this.notifyMessage = configManager != null ? configManager.getStringOrDefault("config.websocket.notify-message", "§c[StreamerBot] Could not connect after %retries% attempts. Check your config or Streamer.bot status.") : "§c[StreamerBot] Could not connect after %retries% attempts. Check your config or Streamer.bot status.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(ServerHandshake handshakedata) {
|
||||
retryCount = 0; // Reset on successful connection
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
// Handle incoming messages from Streamer.bot here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(int code, String reason, boolean remote) {
|
||||
if (retryCount < maxRetries) {
|
||||
retryCount++;
|
||||
try {
|
||||
Thread.sleep(2000L * retryCount); // Exponential backoff
|
||||
} catch (InterruptedException ignored) {}
|
||||
this.reconnect();
|
||||
} else {
|
||||
String msg = notifyMessage.replace("%retries%", String.valueOf(maxRetries));
|
||||
notifyOps(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception ex) {
|
||||
// Optionally log errors
|
||||
}
|
||||
|
||||
private void notifyOps(String message) {
|
||||
Bukkit.getScheduler().runTask(Bukkit.getPluginManager().getPlugin("TikTokStreamPlugin"), () -> {
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
if (player.isOp() || player.hasPermission(notifyPermission)) {
|
||||
player.sendMessage(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
54
src/main/java/com/minster586/ui/NotificationManager.java
Normal file
54
src/main/java/com/minster586/ui/NotificationManager.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package com.minster586.ui;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class NotificationManager {
|
||||
private static final JavaPlugin plugin = JavaPlugin.getProvidingPlugin(NotificationManager.class);
|
||||
|
||||
public static void sendNotification(Player player, ConfigurationSection section, Map<String, String> placeholders) {
|
||||
if (section == null) return;
|
||||
|
||||
String locationsRaw = section.getString("locations", "").toLowerCase();
|
||||
String[] locations = locationsRaw.split(",");
|
||||
|
||||
for (String loc : locations) {
|
||||
switch (loc.trim()) {
|
||||
case "chat":
|
||||
sendChat(player, section.getString("chat-message", ""), placeholders);
|
||||
break;
|
||||
case "action-bar":
|
||||
sendActionBar(player, section.getString("action-bar-message", ""), placeholders);
|
||||
break;
|
||||
default:
|
||||
Bukkit.getLogger().warning("Unknown notification location: " + loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendChat(Player player, String message, Map<String, String> placeholders) {
|
||||
if (message == null || message.isEmpty()) return;
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', replacePlaceholders(message, placeholders)));
|
||||
}
|
||||
|
||||
private static void sendActionBar(Player player, String message, Map<String, String> placeholders) {
|
||||
if (message == null || message.isEmpty()) return;
|
||||
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(replacePlaceholders(message, placeholders)));
|
||||
}
|
||||
|
||||
private static String replacePlaceholders(String input, Map<String, String> placeholders) {
|
||||
if (input == null) return "";
|
||||
for (Map.Entry<String, String> entry : placeholders.entrySet()) {
|
||||
input = input.replace("%" + entry.getKey() + "%", entry.getValue());
|
||||
}
|
||||
return input;
|
||||
}
|
||||
}
|
33
src/main/resources/config.yml
Normal file
33
src/main/resources/config.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
config:
|
||||
prefix: [TikTok]
|
||||
tiktok_username: Change-me #this is the username of your tiktok account with out the "@" symbol
|
||||
giftMappingUrl: "https://yourdomain.com/gift-mapping.yaml" #you can change if need but might want to make sure it follows same scheam
|
||||
|
||||
websocket:
|
||||
url: "ws://localhost:8080" # change IP if need
|
||||
refresh-delay: 6 # this is in seconds
|
||||
retry-count: 3 # Number of times to retry connecting to Streamer.bot
|
||||
notify-permission: "tiktok.live" # Permission required to receive connection failure notifications
|
||||
notify-message: "§c[StreamerBot] Could not connect after %retries% attempts. Check your config or Streamer.bot status."
|
||||
|
||||
settings:
|
||||
join:
|
||||
joined-enabled: true
|
||||
loctions: action-bar #this can be chat, action-bar
|
||||
chat-message: ""
|
||||
action-bar-message: "%username% joined the stream!"
|
||||
gift:
|
||||
gifts-enabled: true
|
||||
loctions: chat #this can be chat, action-bar
|
||||
chat-message: "%prefix% - %username% sent a %giftName%!"
|
||||
action-bar-message: ""
|
||||
chat:
|
||||
chat-enabled: true
|
||||
loctions: chat #this can be chat, action-bar
|
||||
chat-message: "%prefix% - [%username%] > %message%"
|
||||
action-bar-message: ""
|
||||
follows:
|
||||
follow-enabled: true
|
||||
loctions: chat #this can be chat, action-bar
|
||||
chat-message: "%prefix% - [%username%] Followed"
|
||||
action-bar-message: ""
|
16
src/main/resources/plugin.yml
Normal file
16
src/main/resources/plugin.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
name: TikTokStreamPlugin
|
||||
main: com.minster586.tiktokstream.TikTokStreamPlugin
|
||||
version: 1.0.0
|
||||
author: minster586
|
||||
description: Integrates TikTok Live events with Minecraft 1.19
|
||||
api-version: 1.19
|
||||
|
||||
commands:
|
||||
tiktok:
|
||||
description: TikTok live control command
|
||||
usage: /tiktok live <enable|disable>
|
||||
permission: tiktok.live
|
||||
permissions:
|
||||
tiktok.live:
|
||||
description: Allows control of TikTok live notifications
|
||||
default: op
|
Reference in New Issue
Block a user