Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Webhooks & getMemberHighestRole #115

Open
wants to merge 5 commits into
base: djs
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions docs/exports.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ If you have other resources that you wish to be able to use information availabl
- [isRolePresent](#isrolepresent)
- [getDiscordId](#getDiscordId)
- [getRoles](#getroles)
- [getMemberHighestRole](#getMemberHighestRole)
- [getName](#getname)
- [log](#log)
- [registerWebhook](#registerWebhook)
- [sendWebhook](#sendWebhook)

### isRolePresent
Returns a true/false boolean if a role is present for a role id or array of role-ids
Expand Down Expand Up @@ -70,6 +73,26 @@ local roles = exports.zdiscord:getRoles(source);
local roles = exports.zdiscord:getRoles("142831624868855808");
```

### getMemberHighestRole
Returns a name of the member's highest role, using a discord id or source

```js
// JAVASCRIPT EXAMPLE
// Source
const roles = global.exports.zdiscord.getMemberHighestRole(global.source);

// Discord ID
const roles = global.exports.zdiscord.getMemberHighestRole("142831624868855808");
```
```lua
-- LUA EXAMPLE
-- Source
local role = exports.zdiscord:getMemberHighestRole(source);

-- Discord ID
local role = exports.zdiscord:getMemberHighestRole("142831624868855808");
```


### getName
Returns an string containing the discord name/nickname for a discord id or source
Expand Down Expand Up @@ -106,3 +129,45 @@ global.exports.zdiscord.log("modlog", "UserA Banned UserB for Reason", true, "#F
-- event, message, pingRole, color (optional)
exports.zdiscord:log("modlog", "UserA Banned UserB for Reason", true, "#FF0000");
```

### registerWebhook
register a webhook for usage

```js
// JAVASCRIPT EXAMPLE
// name, webhook url
global.exports.zdiscord.registerWebhook("name", "https://discord.com/api/webhooks/id/key");

```
```lua
-- LUA EXAMPLE
-- name, webhook url
exports.zdiscord:registerWebhook("name", "https://discord.com/api/webhooks/id/key");
```

### sendWebhook
send a webhook message, using a name of a webhook you registered

```js
// JAVASCRIPT EXAMPLE
// webhook name, { title, description, footer, username, avatarURL, color }
global.exports.zdiscord.sendWebhook("name", {
title: "title",
description: "desc",
footer: "footer",
username: "username",
color: "#FFFFFF"
});

```
```lua
-- LUA EXAMPLE
-- webhook name, { title, description, footer, username, avatarURL, color }
exports.zdiscord:sendWebhook("name", {
title = "Chat Message",
description = "This is a chat message test!",
footer = "Wow Footer",
username = 'Chat',
color = "#FFFFFF"
});
```
119 changes: 119 additions & 0 deletions optional addons/status_message.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/**
* This file is part of zdiscord.
* Copyright (C) 2021 Tony/zfbx
* source: <https://github.com/zfbx/zdiscord>
*
* This work is licensed under the Creative Commons
* Attribution-NonCommercial-ShareAlike 4.0 International License.
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/
* or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
*
* This Addon was created by [ItzDabbzz](https://github.com/ItzDabbzz)
*
* This addon sends a message with status updates every x number of minutes in a specified channel
* copy this into your `server/addons` folder and edit the channelId to the channel id you want messages sent.
*/

const { MessageEmbed, MessageActionRow, MessageButton } = require("discord.js");


class StatusMessage {
constructor(z) {
// Minutes
this.timerDelay = 5;
// Channel id to send server status updates
this.channelId = "000000000000000000";
// City join ip
this.cityJoinURL = 'cfx.re/join/';
// store message id so we can edit it later
this.messageId = null;
// object to store players in the city
this.inCity = {}


this.z = z;
on("zdiscord:ready", async () => {
this.post();
this.start();
});
}

async start() {
setInterval(() => {
this.post();
}, 1000 * 60 * this.timerDelay);

on("playerJoining", async (oldId) => {
const source = global.source;
const member = this.z.bot.getMemberFromSource(source);
if (!member) return;
const playerName = GetPlayerName(source);
this.inCity[member.id] = {
name: playerName,
id: source,
}
this.post();
})

on("playerDropped", async (reason) => {
const source = global.source;
const member = this.z.bot.getMemberFromSource(source);
delete this.inCity[member.id];
this.post();
})
}

async post() {
try {
const channel = await this.z.bot.channels.fetch(this.channelId);
let playerMessage = `**Current Connected Player(s):**\n\n`;

for (const [key, value] of Object.entries(this.inCity)) {
playerMessage += `[${value.id}] ${value.name} - <@${key}>\n`;
}

if (Object.keys(this.inCity).length === 0) playerMessage = "No Players Online";

const embed = new MessageEmbed()
.setTitle(`${this.z.config.FiveMServerName}`)
.setDescription(`${playerMessage}\n`)
.addFields(
{
name: "Online Players",
value: `\`\`\`${GetNumPlayerIndices()}/${GetConvar("sv_maxClients", "48")}\`\`\``,
inline: true
},
{
name: "Uptime",
value: `\`\`\`${z.utils.timeformat((GetGameTimer() / 1000))}\`\`\``,
inline: true
}
)
.setColor("#00ff00")
.setTimestamp()
const join = new MessageButton()
.setLabel('Join City')
.setURL(this.cityJoinURL)
.setStyle('LINK')
const row = new MessageActionRow()
.addComponents(join);

if (this.messageId) {
const message = await channel.messages.fetch(this.messageId);
message.edit({ embeds: [embed] });
} else {
const message = await channel.send({
embeds: [embed],
components: [row],
});
this.messageId = message.id;
}
}
catch (e) {
console.error(e);
}
}

}

module.exports = StatusMessage;
75 changes: 74 additions & 1 deletion server/bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
*/

const { Client, Collection, MessageEmbed, MessageActionRow, MessageButton } = require("discord.js");
const { Client, Collection, MessageEmbed, MessageActionRow, MessageButton, WebhookClient } = require("discord.js");
const { readdirSync } = require("fs");

class Bot extends Client {
Expand All @@ -28,6 +28,7 @@ class Bot extends Client {
this.utils = z.utils;
this.Embed = MessageEmbed;
this.commands = new Collection();
this.webhooks = new Collection();
this.arrayOfCommands = [];

if (this.enabled) this.start();
Expand Down Expand Up @@ -186,6 +187,21 @@ class Bot extends Client {
return member.roles.cache.map(r => r.id);
}

/** Get the highest role of a discord member
* @param {number|object|string} member - source | member | discordid
* @returns {String|null} - Highest role object or null if no roles
*/
getMemberHighestRole(member) {
if (!member || !this.enabled) return null;
member = this.parseMember(member);
if (!member) return null;
const role = member.roles.cache
.sort((a, b) => b.position - a.position)
.first();
if (!role) return null;
return role.name;
}

hasPermission(member, level) {
switch (level) {
case "mod":
Expand All @@ -204,6 +220,63 @@ class Bot extends Client {
}
}

/** Register a new webhook with a friendly name
* @param {string} name - Friendly name to reference this webhook
* @param {string} url - Discord webhook url
* @returns {Promise<boolean>} - True if registration successful, false if failed
*/
async registerWebhook(name, url) {
try {
const webhook = new WebhookClient({ url: url});
this.webhooks.set(name, webhook);
return true;
} catch (error) {
this.log.error(`Failed to register webhook ${name}: ${error}`);
return false;
}
}

/** Send a message through a registered webhook
* @param {string} name - Friendly name of the registered webhook
* @param {Object} options - Message options
* @param {string} [options.title] - Embed title
* @param {string} [options.description] - Embed description
* @param {string} [options.color] - Hex color code
* @param {string} [options.footer] - Footer text
* @param {string} [options.username] - Override webhook username
* @param {string} [options.avatarURL] - Override webhook avatar
* @returns {Promise<boolean>} - True if message sent successfully, false if failed
*/
async sendWebhookMessage(name, options) {
const webhook = this.webhooks.get(name);
if (!webhook) {
this.log.error(`Webhook ${name} not found`);
return false;
}

const embed = new MessageEmbed()
.setTitle(options.title || '')
.setDescription(options.description || '')
.setColor(options.color || '#ffffff')
.setTimestamp();

if (options.footer) {
embed.setFooter({ text: options.footer });
}

try {
await webhook.send({
username: options.username || webhook.name,
avatarURL: options.avatarURL,
embeds: [embed]
});
return true;
} catch (error) {
this.log.error(`Failed to send webhook message: ${error}`);
return false;
}
}

}

module.exports = Bot;
12 changes: 12 additions & 0 deletions server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ global.exports("getRoles", (identifier) => {
return z.bot.getMemberRoles(identifier);
});

global.exports("getMemberHighestRole", (identifier) => {
return z.bot.getMemberHighestRole(identifier);
});

global.exports("getName", (identifier) => {
const member = z.bot.parseMember(identifier);
return member.displayName || false;
Expand All @@ -137,3 +141,11 @@ global.exports("getName", (identifier) => {
global.exports("getDiscordId", (identifier) => {
return z.utils.getPlayerDiscordId(identifier);
});

global.exports("registerWebhook", (name, webhook) => {
return z.bot.registerWebhook(name, webhook);
});

global.exports("sendWebhook", (name, content) => {
return z.bot.sendWebhookMessage(name, content);
});