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

Add loop messages feature #18

Open
wants to merge 6 commits into
base: main
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
2 changes: 2 additions & 0 deletions features/jobs.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const cooldown = require("./cooldown").default;
const jobs = {
tags: ["forhire", "for hire", "hiring", "remote", "local"],
handleMessage: ({ msg, user }) => {
if (msg.author.bot) return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this strictly necessary?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes? What benefit would we get if we had bots messaging/triggering each other?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is necessary because the bot may post a message in the #jobs channel that does not contain these tags so it would receive a warning from itself


let hasTags = false;
jobs.tags.forEach(tag => {
if (msg.content.toLowerCase().includes(`[${tag}]`)) hasTags = true;
Expand Down
75 changes: 75 additions & 0 deletions features/loopMessages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* ------------------------------
* Loop Messages
* ------------------------------
* The bot will keep a message as the last one in a channel, with an interval between each post,
* to keep important information more visible to users
*
* How it works:
* At startup and repeatedly by a given interval, for each loop message, the bot will:
* 1. Get the target channel of the loop message
* 2. Fetch the last 50 messages of the channel
* 3. If the last message is already the message we want to loop, do nothing (we don't want to spam the channel)
* 4. Delete all loop messages (so the channel isn't filled with bot messages)
* 5. Send the loop message
*/

const loopMessages = require("./messages.js");

// if the interval is not specified in the msg object, then we will use this one
const DEFAULT_INTERVAL_TIME = 60 * 60 * 1000; // 1 hour (ms)

function getContent(loopMessage) {
return loopMessage.trim();
}

function isMessageFromBot(bot, message) {
return message.author.id === bot.user.id;
}

function isLoopMessage(messageToCheck, loopMessage, bot) {
return (
isMessageFromBot(bot, messageToCheck) &&
messageToCheck.content.trim() === getContent(loopMessage.content)
);
}

async function sendLoopMessage(client, loopMessage) {
const channel = client.channels.get(loopMessage.channelId);
const channelMessages = await channel.fetchMessages({
limit: 50 // we don't need to worry about deleting old messages
});

// if the last message in the channel is from the bot, we don't need to send it again
if (isLoopMessage(channelMessages.first(), loopMessage, client)) {
return;
}

// search through all the last messages for the loop message, so we can delete it
channelMessages.forEach(message => {
if (isLoopMessage(message, loopMessage, client)) {
message.delete();
}
});

// now we can send the loop message in the channel
channel.send(getContent(loopMessage.content));
}

module.exports = {
register: (client, logger) => {
client.on("ready", () => {
loopMessages.forEach(message => {
sendLoopMessage(client, message); // initial run on startup

const interval = message.interval || DEFAULT_INTERVAL_TIME;

setInterval(() => {
sendLoopMessage(client, message);
}, interval);
});

logger.log("INI", "Registered Loop Messages");
});
}
};
20 changes: 20 additions & 0 deletions features/loopMessages/messages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = [
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am using a JS file instead of JSON because of the comments that are useful with channelId and the template strings for the multi-line messages

{
channelId: "600037610005463050", // #another
interval: 40 * 60 * 1000, // 40 minutes (ms)
content: `

:arrows_clockwise: __PLEASE READ BEFORE POSTING__ :pushpin:

Job post search: http://jobs.reactiflux.com/

Messages must start with [FORHIRE] or [HIRING].
Lead with the location of the position and include LOCAL, REMOTE, INTERN, VISA, etc.

Please only post jobs once a week.

Jobs are paid—unpaid and equity-only positions may not be posted here.

`
}
];
4 changes: 4 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const autoban = require("./features/autoban").default;
const commands = require("./features/commands").default;
const witInvite = require("./features/wit-invite").default;
const stats = require("./features/stats").default;
const loopMessages = require("./features/loopMessages");

const bot = new discord.Client();
bot.login(process.env.DISCORD_HASH);
Expand Down Expand Up @@ -81,6 +82,9 @@ logger.add(channelLog(bot, "479862475047567361"));
// Amplitude metrics
stats(bot);

// Loop Messages
loopMessages.register(bot, logger);

// reactiflux
channelHandlers.addHandler("103882387330457600", jobs);
channelHandlers.addHandler("541673256596537366", witInvite); // #women-in-tech
Expand Down