mirror of
https://github.com/ZareMate/kubejs.git
synced 2026-11-12 14:20:29 +00:00
feat: added webhook support
This commit is contained in:
+305
-210
@@ -11,286 +11,381 @@
|
||||
* The original author attribution and copyright notice must remain.
|
||||
*/
|
||||
|
||||
// Dependencies: LuckPerms, KubeJSHTTP
|
||||
|
||||
// Dependencies: LuckPerms
|
||||
var DISCORD_WEBHOOK_URL = "REPLACE_ME";
|
||||
|
||||
|
||||
var DISCORD_WEBHOOK_URL = 'REPLACE_ME';
|
||||
|
||||
var MULTIACCOUNT_PERMISSION_CHECKIP = 'multiaccount.command.checkip';
|
||||
var MULTIACCOUNT_PERMISSION_ALERT = 'multiaccount.alert';
|
||||
var MULTIACCOUNT_PERMISSION_CHECKIP = "multiaccount.command.checkip";
|
||||
var MULTIACCOUNT_PERMISSION_ALERT = "multiaccount.alert";
|
||||
|
||||
var LuckPermsApiProvider = Java.loadClass(
|
||||
'net.luckperms.api.LuckPermsProvider'
|
||||
"net.luckperms.api.LuckPermsProvider",
|
||||
);
|
||||
|
||||
var HttpAPI = Java.loadClass("com.awizo.KubeJSHTTP.HttpAPI");
|
||||
|
||||
var luckPermsApi = null;
|
||||
var playerIPMap = new Map();
|
||||
|
||||
function getLuckPerms() {
|
||||
if (luckPermsApi) {
|
||||
return luckPermsApi;
|
||||
}
|
||||
if (luckPermsApi) {
|
||||
return luckPermsApi;
|
||||
}
|
||||
|
||||
try {
|
||||
luckPermsApi = LuckPermsApiProvider.get();
|
||||
try {
|
||||
luckPermsApi = LuckPermsApiProvider.get();
|
||||
|
||||
console.log('[Multi-Account] luckPermsApi API loaded successfully!');
|
||||
console.log("[Multi-Account] luckPermsApi API loaded successfully!");
|
||||
|
||||
return luckPermsApi;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
return luckPermsApi;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function hasPermission(player, permission) {
|
||||
var api = getLuckPerms();
|
||||
var api = getLuckPerms();
|
||||
|
||||
if (!api || !player) {
|
||||
return false;
|
||||
}
|
||||
if (!api || !player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return api
|
||||
.getUserManager()
|
||||
.getUser(player.uuid)
|
||||
.getCachedData()
|
||||
.getPermissionData()
|
||||
.checkPermission(permission)
|
||||
.asBoolean();
|
||||
} catch (error) {
|
||||
console.error(
|
||||
'[Multi-Account] Failed to check permission ' +
|
||||
permission +
|
||||
' for ' +
|
||||
player.username +
|
||||
': ' +
|
||||
error
|
||||
);
|
||||
try {
|
||||
return api
|
||||
.getUserManager()
|
||||
.getUser(player.uuid)
|
||||
.getCachedData()
|
||||
.getPermissionData()
|
||||
.checkPermission(permission)
|
||||
.asBoolean();
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"[Multi-Account] Failed to check permission " +
|
||||
permission +
|
||||
" for " +
|
||||
player.username +
|
||||
": " +
|
||||
error,
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getPlayerIP(player) {
|
||||
try {
|
||||
var ip = player.ipAddress;
|
||||
try {
|
||||
var ip = player.ipAddress;
|
||||
|
||||
if (!ip) {
|
||||
return null;
|
||||
}
|
||||
if (!ip) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ip.includes('/')) {
|
||||
ip = ip.split('/')[1];
|
||||
}
|
||||
if (ip.includes("/")) {
|
||||
ip = ip.split("/")[1];
|
||||
}
|
||||
|
||||
if (ip.includes(':')) {
|
||||
ip = ip.split(':')[0];
|
||||
}
|
||||
if (ip.includes(":")) {
|
||||
ip = ip.split(":")[0];
|
||||
}
|
||||
|
||||
return ip;
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
'[Multi-Account] Failed to get IP for ' +
|
||||
player.username +
|
||||
': ' +
|
||||
error
|
||||
);
|
||||
return ip;
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
"[Multi-Account] Failed to get IP for " +
|
||||
player.username +
|
||||
": " +
|
||||
error,
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function sendPlayerNotification(player, otherPlayers) {
|
||||
player.tell(
|
||||
'§c[ALERT] §fMulti-account detected! Other accounts on your IP: §e' +
|
||||
otherPlayers.join(', ')
|
||||
);
|
||||
player.tell(
|
||||
"§c[ALERT] §fMulti-account detected! Other accounts on your IP: §e" +
|
||||
otherPlayers.join(", "),
|
||||
);
|
||||
}
|
||||
|
||||
function notifyStaff(server, playerName, otherPlayers) {
|
||||
var message =
|
||||
'§c[ADMIN] §fPlayer §6' +
|
||||
playerName +
|
||||
'§f has the same IP as: §e' +
|
||||
otherPlayers.join(', ');
|
||||
var message =
|
||||
"§c[ADMIN] §fPlayer §6" +
|
||||
playerName +
|
||||
"§f has the same IP as: §e" +
|
||||
otherPlayers.join(", ");
|
||||
|
||||
server.players.forEach(player => {
|
||||
if (hasPermission(player, MULTIACCOUNT_PERMISSION_ALERT)) {
|
||||
player.tell(message);
|
||||
}
|
||||
});
|
||||
server.players.forEach((player) => {
|
||||
if (hasPermission(player, MULTIACCOUNT_PERMISSION_ALERT)) {
|
||||
player.tell(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function sendDiscordNotification(server, playerName, otherPlayers) {
|
||||
var payload = {
|
||||
content: '⚠️ **MULTI-ACCOUNT DETECTED**',
|
||||
embeds: [{
|
||||
title: 'Multi-Account Alert',
|
||||
color: 16711680,
|
||||
fields: [
|
||||
{
|
||||
name: 'Player',
|
||||
value: playerName,
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: 'Other Accounts on IP',
|
||||
value: otherPlayers.join(', '),
|
||||
inline: false
|
||||
},
|
||||
{
|
||||
name: 'Timestamp',
|
||||
value: new Date().toISOString(),
|
||||
inline: true
|
||||
}
|
||||
]
|
||||
}]
|
||||
};
|
||||
function sendDiscordNotification(player, otherPlayers) {
|
||||
var playerName =
|
||||
player && typeof player.getName === "function"
|
||||
? player.getName().getString()
|
||||
: "Unknown";
|
||||
|
||||
try {
|
||||
HttpAPI.post(
|
||||
DISCORD_WEBHOOK_URL,
|
||||
JSON.stringify({
|
||||
embeds: [
|
||||
{
|
||||
title: "Multi-Account Alert",
|
||||
description:
|
||||
"Player: " +
|
||||
playerName +
|
||||
"\n" +
|
||||
"Other Accounts on IP: " +
|
||||
otherPlayers.join(", ") +
|
||||
"\n" +
|
||||
"Timestamp: <t:" +
|
||||
Math.floor(Date.now() / 1000) +
|
||||
":S>",
|
||||
color: 3447003,
|
||||
footer: {
|
||||
text: "Sputnik watch",
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
} catch (e) {
|
||||
console.error("[SputnikWatch] Failed to send webhook: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
function rebuildPlayerIPMap(server) {
|
||||
playerIPMap.clear();
|
||||
|
||||
server.players.forEach((player) => {
|
||||
var name = player.username;
|
||||
var ip = getPlayerIP(player);
|
||||
|
||||
if (!ip) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!playerIPMap.has(ip)) {
|
||||
playerIPMap.set(ip, new Set());
|
||||
}
|
||||
|
||||
playerIPMap.get(ip).add(name);
|
||||
});
|
||||
|
||||
console.log(
|
||||
"[Multi-Account] IP map rebuilt. Tracking " +
|
||||
playerIPMap.size +
|
||||
" IP(s).",
|
||||
);
|
||||
}
|
||||
|
||||
function sendCheckIPWebhook(player, groups) {
|
||||
var playerName =
|
||||
player && typeof player.getName === "function"
|
||||
? player.getName().getString()
|
||||
: "Unknown";
|
||||
|
||||
if (groups.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var groupText = groups
|
||||
.map((players, index) => {
|
||||
return "**Group " + (index + 1) + ":** " + players.join(", ");
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
try {
|
||||
HttpAPI.post(
|
||||
DISCORD_WEBHOOK_URL,
|
||||
JSON.stringify({
|
||||
embeds: [
|
||||
{
|
||||
title: "IP Check",
|
||||
description:
|
||||
"Requested by: " +
|
||||
playerName +
|
||||
"\n\n" +
|
||||
groupText +
|
||||
"\n\n" +
|
||||
"Timestamp: <t:" +
|
||||
Math.floor(Date.now() / 1000) +
|
||||
":S>",
|
||||
color: 3447003,
|
||||
footer: {
|
||||
text: "Sputnik watch",
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
console.log("[Multi-Account] /checkip results sent to Discord.");
|
||||
} catch (e) {
|
||||
console.error("[SputnikWatch] Failed to send /checkip webhook: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
function checkMultiAccount(server, player) {
|
||||
var name = player.username;
|
||||
var ip = getPlayerIP(player);
|
||||
var name = player.username;
|
||||
var ip = getPlayerIP(player);
|
||||
|
||||
if (!ip) {
|
||||
return;
|
||||
}
|
||||
if (!ip) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!playerIPMap.has(ip)) {
|
||||
playerIPMap.set(ip, new Set());
|
||||
}
|
||||
if (!playerIPMap.has(ip)) {
|
||||
playerIPMap.set(ip, new Set());
|
||||
}
|
||||
|
||||
var players = playerIPMap.get(ip);
|
||||
var otherPlayers = Array.from(players).filter(
|
||||
playerName => playerName !== name
|
||||
);
|
||||
var players = playerIPMap.get(ip);
|
||||
|
||||
if (otherPlayers.length > 0) {
|
||||
console.log(
|
||||
'[Multi-Account] ALERT: ' +
|
||||
name +
|
||||
' shares IP with: ' +
|
||||
otherPlayers.join(', ')
|
||||
);
|
||||
var otherPlayers = Array.from(players).filter(
|
||||
(playerName) => playerName !== name,
|
||||
);
|
||||
|
||||
sendPlayerNotification(player, otherPlayers);
|
||||
notifyStaff(server, name, otherPlayers);
|
||||
sendDiscordNotification(server, name, otherPlayers);
|
||||
}
|
||||
if (otherPlayers.length > 0) {
|
||||
console.log(
|
||||
"[Multi-Account] ALERT: " +
|
||||
name +
|
||||
" shares IP with: " +
|
||||
otherPlayers.join(", "),
|
||||
);
|
||||
|
||||
players.add(name);
|
||||
sendPlayerNotification(player, otherPlayers);
|
||||
|
||||
notifyStaff(server, name, otherPlayers);
|
||||
|
||||
sendDiscordNotification(player, otherPlayers);
|
||||
}
|
||||
|
||||
players.add(name);
|
||||
}
|
||||
|
||||
function removePlayer(name) {
|
||||
for (var [ip, players] of playerIPMap) {
|
||||
if (!players.delete(name)) {
|
||||
continue;
|
||||
}
|
||||
for (var [ip, players] of playerIPMap) {
|
||||
if (!players.delete(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
console.log(
|
||||
'[Multi-Account] Removed ' +
|
||||
name +
|
||||
' from IP tracking (' +
|
||||
ip +
|
||||
')'
|
||||
);
|
||||
console.log(
|
||||
"[Multi-Account] Removed " +
|
||||
name +
|
||||
" from IP tracking (" +
|
||||
ip +
|
||||
")",
|
||||
);
|
||||
|
||||
if (players.size === 0) {
|
||||
playerIPMap.delete(ip);
|
||||
}
|
||||
if (players.size === 0) {
|
||||
playerIPMap.delete(ip);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PlayerEvents.loggedIn(event => {
|
||||
var player = event.player;
|
||||
var server = event.server;
|
||||
PlayerEvents.loggedIn((event) => {
|
||||
var player = event.player;
|
||||
var server = event.server;
|
||||
|
||||
console.log(
|
||||
'[Multi-Account] ' +
|
||||
player.username +
|
||||
' joined from: ' +
|
||||
getPlayerIP(player)
|
||||
);
|
||||
console.log(
|
||||
"[Multi-Account] " +
|
||||
player.username +
|
||||
" joined from: " +
|
||||
getPlayerIP(player),
|
||||
);
|
||||
|
||||
server.schedule(10, () => {
|
||||
checkMultiAccount(server, player);
|
||||
});
|
||||
server.schedule(10, () => {
|
||||
checkMultiAccount(server, player);
|
||||
});
|
||||
});
|
||||
|
||||
PlayerEvents.loggedOut(event => {
|
||||
var name = event.player.username;
|
||||
PlayerEvents.loggedOut((event) => {
|
||||
var name = event.player.username;
|
||||
|
||||
console.log(
|
||||
'[Multi-Account] ' +
|
||||
name +
|
||||
' left the server'
|
||||
);
|
||||
console.log("[Multi-Account] " + name + " left the server");
|
||||
|
||||
removePlayer(name);
|
||||
removePlayer(name);
|
||||
});
|
||||
|
||||
ServerEvents.commandRegistry(event => {
|
||||
const { commands: Commands } = event;
|
||||
ServerEvents.commandRegistry((event) => {
|
||||
const { commands: Commands } = event;
|
||||
|
||||
event.register(
|
||||
Commands.literal('checkip')
|
||||
.requires(source =>
|
||||
source.isPlayer() &&
|
||||
(
|
||||
source.hasPermission(3) ||
|
||||
hasPermission(
|
||||
source.player,
|
||||
MULTIACCOUNT_PERMISSION_CHECKIP
|
||||
)
|
||||
)
|
||||
)
|
||||
.executes(ctx => {
|
||||
var source = ctx.source;
|
||||
var group = 1;
|
||||
var found = false;
|
||||
event.register(
|
||||
Commands.literal("checkip")
|
||||
.requires(
|
||||
(source) =>
|
||||
source.isPlayer() &&
|
||||
(source.hasPermission(3) ||
|
||||
hasPermission(
|
||||
source.player,
|
||||
MULTIACCOUNT_PERMISSION_CHECKIP,
|
||||
)),
|
||||
)
|
||||
.executes((ctx) => {
|
||||
var source = ctx.source;
|
||||
var server = source.server;
|
||||
|
||||
source.sendSuccess(
|
||||
Text.of('§6Players sharing an IP:'),
|
||||
false
|
||||
);
|
||||
var group = 1;
|
||||
var found = false;
|
||||
var groups = [];
|
||||
|
||||
for (var players of playerIPMap.values()) {
|
||||
if (players.size <= 1) {
|
||||
continue;
|
||||
}
|
||||
rebuildPlayerIPMap(server);
|
||||
|
||||
found = true;
|
||||
source.sendSuccess(Text.of("§6Players sharing an IP:"), false);
|
||||
|
||||
source.sendSuccess(
|
||||
Text.of(
|
||||
`§7Group ${group}: §e${Array.from(players).join(', ')}`
|
||||
),
|
||||
false
|
||||
);
|
||||
for (var players of playerIPMap.values()) {
|
||||
if (players.size <= 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
group++;
|
||||
}
|
||||
found = true;
|
||||
|
||||
if (!found) {
|
||||
source.sendSuccess(
|
||||
Text.of('§7No players currently share an IP.'),
|
||||
false
|
||||
);
|
||||
}
|
||||
var playerList = Array.from(players);
|
||||
|
||||
return 1;
|
||||
})
|
||||
);
|
||||
groups.push(playerList);
|
||||
|
||||
source.sendSuccess(
|
||||
Text.of(`§7Group ${group}: §e${playerList.join(", ")}`),
|
||||
false,
|
||||
);
|
||||
|
||||
group++;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
source.sendSuccess(
|
||||
Text.of("§7No players currently share an IP."),
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
sendCheckIPWebhook(source.player, groups);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
console.log('[Multi-Account] Script loaded successfully!');
|
||||
console.log('[Multi-Account] /checkip permission: ' + MULTIACCOUNT_PERMISSION_CHECKIP);
|
||||
console.log('[Multi-Account] Chat alert permission: ' + MULTIACCOUNT_PERMISSION_ALERT);
|
||||
console.log('[Multi-Account] Commands: /checkip');
|
||||
console.log("[Multi-Account] Script loaded successfully!");
|
||||
|
||||
console.log(
|
||||
'[Multi-Account] Webhook: ' +
|
||||
(DISCORD_WEBHOOK_URL !== 'REPLACE_ME' ? '✓ Configured' : '✗ Not configured')
|
||||
"[Multi-Account] /checkip permission: " + MULTIACCOUNT_PERMISSION_CHECKIP,
|
||||
);
|
||||
|
||||
console.log(
|
||||
"[Multi-Account] Chat alert permission: " + MULTIACCOUNT_PERMISSION_ALERT,
|
||||
);
|
||||
|
||||
console.log("[Multi-Account] Commands: /checkip");
|
||||
|
||||
console.log(
|
||||
"[Multi-Account] Webhook: " +
|
||||
(DISCORD_WEBHOOK_URL !== "REPLACE_ME"
|
||||
? "✓ Configured"
|
||||
: "✗ Not configured"),
|
||||
);
|
||||
Reference in New Issue
Block a user