Skip to content

Commit

Permalink
Merge pull request #123 from Mirasaki/delayed-kill-feed
Browse files Browse the repository at this point in the history
feat: delayed kill-feed
  • Loading branch information
Mirasaki authored Aug 19, 2023
2 parents 5779cd0 + fcd730e commit d1a4243
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 54 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@

- Discord > DayZ live chat feed - comes with a tag system and is **very** customizable
- Watch List - Receive role-ping notifications when a player in a custom managed list logs in
- Delayed Killfeed - Delay kill webhook messages (configurable) before forwarding them to a different/public channel
- Player Lists

- Public list
Expand Down
17 changes: 11 additions & 6 deletions config/servers.example.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
/**
* SEE the README.md file for explanation and details
*/

const { clientConfig } = require('../src/util');
const colors = require('../config/colors.json');

/**
* For more information:
* {@link https://wiki.mirasaki.dev/docs/cftools-discord-bot/server-configuration}
*/
module.exports = [
{
// Server data
NAME: 'My Server 😎',
CFTOOLS_SERVER_API_ID: 'YOUR_SERVER_API_ID',
SERVER_IPV4: '0.0.0.0',
SERVER_PORT: 2302,
CFTOOLS_WEBHOOK_CHANNEL_ID: '806479539110674472',
CFTOOLS_WEBHOOK_USER_ID: '290182686365188096',

// Command config
STATISTICS_INCLUDE_ZONES_HEATMAP: true,
Expand Down Expand Up @@ -58,8 +60,11 @@ module.exports = [
// Watch list config
WATCH_LIST_CHANNEL_ID: '806479539110674472',
WATCH_LIST_NOTIFICATION_ROLE_ID: '1112020551817502860',
CFTOOLS_WEBHOOK_CHANNEL_ID: '806479539110674472',
CFTOOLS_WEBHOOK_USER_ID: '290182686365188096',

// Kill Feed config
USE_KILL_FEED: true,
KILL_FEED_DELAY: 5,
KILL_FEED_CHANNEL_ID: '806479539110674472',

// Leaderboard config
LEADERBOARD_DEFAULT_SORTING_STAT: 'OVERALL',
Expand Down
6 changes: 5 additions & 1 deletion src/listeners/messageCreate.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { MS_IN_ONE_SECOND } = require('../constants');
const { serverConfig, broadcastMessage } = require('../modules/cftClient');
const { checkIsDelayedKillFeedMsg } = require('../modules/delayed-kill-feed');
const { checkIsWatchListMsg } = require('../modules/watch-list');
const { debugLog } = require('../util');

Expand All @@ -25,7 +26,10 @@ module.exports = async (client, msg) => {
if (!content || content.length === 0) return;

// Run watch list checks
checkIsWatchListMsg(msg, client);
checkIsWatchListMsg(msg);

// Run delayed kill feed checks
checkIsDelayedKillFeedMsg(msg);

// Member property isn't available, which is required
// This can happen in partial API outages
Expand Down
46 changes: 46 additions & 0 deletions src/modules/delayed-kill-feed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const { serverConfig } = require('./cftClient');
const { isValidWebhookConfigMessage } = require('./webhooks');

const checkIsDelayedKillFeedMsg = async (msg) => {
const {
channelId,
webhookId,
author,
cleanContent
} = msg;
const isKillMsg = cleanContent.indexOf(' got killed by ') >= 0;
if (!isKillMsg) return false;

for await (const cfg of serverConfig) {
const {
USE_KILL_FEED,
KILL_FEED_DELAY,
KILL_FEED_CHANNEL_ID,
CFTOOLS_WEBHOOK_CHANNEL_ID,
CFTOOLS_WEBHOOK_USER_ID
} = cfg;
const isTargetChannel = channelId === CFTOOLS_WEBHOOK_CHANNEL_ID;
const isTargetUser = CFTOOLS_WEBHOOK_USER_ID === (
process.env.NODE_ENV === 'production'
? webhookId
: author.id
);

// Validate target ids/is webhook message
if (!USE_KILL_FEED || !isTargetChannel || !isTargetUser) continue;

// Resolve target channel
const webhookTargetChannel = isValidWebhookConfigMessage(msg, KILL_FEED_CHANNEL_ID);
if (!webhookTargetChannel) continue;

// Send the notification
await new Promise((resolve) => {
setTimeout(async () => {
const feedMsg = await webhookTargetChannel.send(cleanContent);
resolve(feedMsg);
}, KILL_FEED_DELAY * 1000);
});
}
};

module.exports = { checkIsDelayedKillFeedMsg };
50 changes: 3 additions & 47 deletions src/modules/watch-list.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
const { ChannelType } = require('discord.js');
const { serverConfig } = require('./cftClient');
const { stripIndents } = require('common-tags');
const { getGuildSettings } = require('./db');
const { isValidWebhookConfigMessage } = require('./webhooks');

/**
* @param {Message} msg
* @param {Client} client
*/
const checkIsWatchListMsg = async (msg, client) => {
const checkIsWatchListMsg = async (msg) => {
const {
guild,
channelId,
Expand Down Expand Up @@ -52,43 +47,4 @@ const checkIsWatchListMsg = async (msg, client) => {
}
};

const isValidWebhookConfigMessage = (
msg,
targetChannelId
) => {
// Destructure from message
const { id: msgId,
guild } = msg;

// Return if target can't be resolved
const targetChannel = guild.channels.cache.get(targetChannelId);
if (!targetChannel) {
console.error(stripIndents`
[${ msgId }] Can't send watch-list message, targetChannelId channel from config can't be resolved: ${ targetChannelId }
`);
return false;
}

// Return if target is not text based
else if (!targetChannel.isTextBased()) {
console.error(stripIndents`
[${ msgId }] Can't send watch-list message, targetChannelId channel is NOT a text based channel
`);
return false;
}

// Don't allow stage channels - which have linked text chat
else if (targetChannel.type === ChannelType.GuildStageVoice) {
console.error(stripIndents`
[${ msgId }] Can't send watch-list message, targetChannelId channel is NOT a valid text based channel
`);
return false;
}

// Configuration is valid
else return targetChannel;
};

module.exports = {
checkIsWatchListMsg, isValidWebhookConfigMessage
};
module.exports = { checkIsWatchListMsg };
41 changes: 41 additions & 0 deletions src/modules/webhooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const { stripIndents } = require('common-tags');
const { ChannelType } = require('discord.js');

const isValidWebhookConfigMessage = (
msg,
targetChannelId
) => {
// Destructure from message
const { id: msgId,
guild } = msg;

// Return if target can't be resolved
const targetChannel = guild.channels.cache.get(targetChannelId);
if (!targetChannel) {
console.error(stripIndents`
[${ msgId }] Can't send watch-list message, targetChannelId channel from config can't be resolved: ${ targetChannelId }
`);
return false;
}

// Return if target is not text based
else if (!targetChannel.isTextBased()) {
console.error(stripIndents`
[${ msgId }] Can't send watch-list message, targetChannelId channel is NOT a text based channel
`);
return false;
}

// Don't allow stage channels - which have linked text chat
else if (targetChannel.type === ChannelType.GuildStageVoice) {
console.error(stripIndents`
[${ msgId }] Can't send watch-list message, targetChannelId channel is NOT a valid text based channel
`);
return false;
}

// Configuration is valid
else return targetChannel;
};

module.exports = { isValidWebhookConfigMessage };

0 comments on commit d1a4243

Please sign in to comment.