Looking for a way to send completely unsolicited messages to my discord channel using discord.js.
Background: I have a nodejs app running on my desktop that is monitoring a few websites and I need to notify my team so they can deal with things as the problem evolves. It's an ongoing issue which I'm not getting into right now. Yes, I want to pay for a pro website monitor, but the bean-counters yadda yadda...
I've read through the docs but it seems everything is geared towards event-driven behaviour from the discord side e.g. a new user arrives, a typed command is entered etc
I don't want that. I just want to send a notification when the server that I'm monitoring does X thing.
Here is what I have so far:
const Discord = require('discord.js');
config.discord.client = new Discord.Client();
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
if(shitgoesdown){
new Discord.Message(config.discord.client, data, config.discord.channel);
}
I can't seem to find anything on how to just point this thing at my server. The docs are great and all but they are super dense and right now it's just information overload. If someone could just point at the sign that would be great.
You can fetch the channel using client.channels.fetch(/* Channel ID */) and send a message in the callback using channel.send().
const Discord = require('discord.js');
const client = new Discord.Client();
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
// Code to execute when something happens
client.channels.fetch(/* Channel ID */).then(channel => {
channel.send('Some message');
});
Related
I've just developed a bot for adding roles to a user who starts streaming on my server. When I tested the bot on a isolated server with only a few channels and users the bot responded instantly. But now I have set up my bot on my primary Discord server with roughly 25 channels and about ~500 users and now the response time is more than five minutes before I see it add or remove a role.
I am connecting via FIOS gigabit and running on a I9 with DDR4 4266MHz RAM.
When I first start the node server I notice the delay is much less, however still very slow responses of around a minute or two before it adds or removes the roles. If I allow the server to run for ten minutes then the response time is around five minutes before it adds a role. I do not know if it continues to get worse over time. But what could be causing this delay? I see my user status change to streaming (purple dot) in the online users list immediately, but my discord bot is not aware of this for a very long time!
This is my code, I have tried my best to optimize it but I've only been learning Discord.js for about a week and am still very unfamiliar with it:
// require the discord.js module
const Discord = require('discord.js');
// create a new Discord client
const client = new Discord.Client();
let role = '';
client.once('ready', () => {
const myGuild = client.guilds.cache.get('123456789123456789');
role = myGuild.roles.cache.find(role => role.name === 'streaming');
console.log('Ready!');
});
client.on("presenceUpdate", (oldPresence, newPresence) => {
if (!newPresence.activities){ return false; }
newPresence.activities.forEach(activity => {
if (activity.type == "STREAMING") {
//console.log(`${newPresence.user.tag} is streaming at ${activity.url}.`);
newPresence.member.roles.add(role)
} else {
newPresence.member.roles.remove(role)
};
});
});
// login to Discord with your app's token
client.login('123456789123456789.123456789.123456789123456789');
Can someone please explain why my bot is becoming so sluggish? It is almost unusable and kind of discouraging.
The default maxListeners is set to 10 and it may be worth exploring setting that value higher.
Additionally, I am curious if there is a memory leak on your application.
It sounds like it from the sluggishness that is experienced over time.
Try using a profiling tool like Clinic.js to monitor the state of the application over time.
I wanted to inquire on something I’ve been trying to do recently. I have a Discord.JS bot, and it’s pretty public (130+ servers), and I want it to send a message to any channel in every single server it’s in, when the bot starts up, the purpose is to create a “New Update” notification in one of the channels.
Please do not plan on doing this, as this will get you rate limited really quickly.
This is kind of possible. There is a problem, there is no default guild channel, so you cannot get their "main" channel just by their guild object. If you would want to do that you, would need them to select their channel and store that ID somewhere.
This is a simple solution, where you loop through every guild of your Discord client, and send some channel a message. You don't know what channel with this solution specifically, but you will send some channel a message if it is not a voice channel.
const Discord = require("discord.js");
require("dotenv").config();
// Creating our Client
const client = new Discord.Client();
// Event listener: when the bot is ready
client.on("ready", () => {
// Looping through every guild the bot is in
client.guilds.cache.forEach((guild) => {
// Getting one of their channels
let channel = guild.channels.cache.array()[2];
// Sending the channel a message
channel.send("Hey");
});
});
client.login(process.env.DISCORD_BOT_TOKEN);
I have created a discord bot by taking reference from this digital ocean link.
Now I can send message to any channel using the bot but my requirement is to send dm to user of that server.
For that I have tried many SO answers and followed other links, but all the solutions end up to be same.
I have tried this two way to get the users of a guild and send dm to any one selected user.
1st way - Get all users of guild (server)
const client_notification = new Discord.Client();
client_notification.on('ready', () => {
console.log("Notification manager ready");
let guild = client_notification.guilds.cache.get("Server ID");
guild.members.cache.forEach(member => console.log("===>>>", member.user.username));
});
client_notification.login("login");
Output
Notification manager ready
===>>> discord notification
By this way it only returns me the bot name itself. Although the membersCount is 6.
2nd way - send dm to user directly (server)
client.users.cache.get('<id>').send('<message>');
It gives me undefined in output.
My configs,
Node version: 10.16.3
discord.js version: 12.5.1
My question is how to get all the guild members in discord.js?
Discord added privileged gateway intents recently. So to fetch all member data you need to enable that in the developer portal. After that you need to fetch all the members available, for that we can use the fetchAllMembers client option, and then we need to filter out bot users, so that we don't message them.
const client_notification = new Discord.Client({fetchAllMembers:true}); //Fetches all members available on startup.
client_notification.on('ready', () => {
console.log("Notification manager ready");
let guild = client_notification.guilds.cache.get("Server ID");
guild.members.cache.filter(member => !member.user.bot).forEach(member => console.log("===>>>", member.user.username));
});
client_notification.login("login");
The .filter() method filters out all the bots and gives only the real users.
You should avoid using fetchAllMembers when your bot gets larger though, as it could slow down your bot and use lots of memory.
I think the problem is related to updating the bot policy for discord. Do you have this checkbox checked in the bot settings?
https://discord.com/developers/applications
Some info about client.users.cache:
Its a cache collection, so if you restart bot, or bot never handle user message or actions before, this collection will be empty. Better use guild.members.cache.get('')
I want to deploy a Discord bot running on discord.js to Firebase Cloud Functions but I can't get the bot to run in Firebase. If I use nodemon it runs perfectly but if I use firebase deploy it will not start the bot.
Here is my current code:
const functions = require('firebase-functions');
require('dotenv').config();
const token = process.env.TOKEN
const Discord = require('discord.js')
const Client = new Discord.Client();
Client.on('ready', () => {
Client.channels.find(x => x.name === 'main-cannel').send('bot is deployed')
Client.user.setGame(`The Cult | ${Client.guilds.size} servers`)
Console.log('test')
});
Client.login(token);
//is is not working but de basic
//export.App = functions.... {Client}
exports.app = functions.https.onRequest((request, response) => {
response.send("Test");
});
This may not be the best combination of google cloud platform services, since cloud functions where not designed with this in mind. You can just host your Discord bot on a compute engine machine.
If you want to use the dynamic scaling have a look at Discord Microservice Bots where DasWolke describes what microservices are. Hey also included his javascript code to split up the different services for Discord.
What you can do on Google cloud platform specifically, is creating a VM with the Gateway running. This needs to run 24/7 and should be lightweight. You can use an f1-micro (which is free) for this though google recommends a g1-small for the task.
The gateway should filter the events you are looking for (because Discord sends a lot of events and you don't need most) and send the data to cloud function or cloud run (you can send the data via pub/sub). In my experience, a cloud run has much shorter startup times so I went with that.
Inside your function, you receive the data do with it what you want. If you want something in Discord (send a message, manage channels, ...) you can use SnowTransfer for that. SnowTransfer just calls the rest API on discord.
Put client.login(token) into where response.send("Test"); is. This will prompt your bot's code to execute upon an HTTP request.
In https://us-central1-<your project ID>.cloudfunctions.net/app, replace <your project ID> with your project's ID.
If Firebase Hosting gives you the URL example-123.web.app, your project ID is example-123. You can also get your project ID through the console: open the Firebase console, select your project, click the settings icon, go to "Project settings," and its ID is on the second line of the table.
For this to work, you have to move your token straight into the code. You can't use a shell file like .env.
In the end, your code will be:
const functions = require('firebase-functions');
const token = 'whatever the token is';
const Discord = require('discord.js')
const Client = new Discord.Client();
Client.on('ready', () => {
Client.channels.find(x => x.name === 'main-cannel').send('bot is deployed')
Client.user.setGame(`The Cult | ${Client.guilds.size} servers`)
Console.log('test')
});
exports.app = functions.https.onRequest((request, response) => {
response.send("Test"); // Do not delete this! Your request will time out if you do.
Client.login(token);
});
As Gabber235 noted, this is probably not the best Google Cloud Platform service to use for this, and you should probably use Compute Engine.
I have a bot that is identical to the one demonstrated in the docs quickstart. It repeats back whatever the user says (for now).
It is currently running locally and exposed with ngrok. I've registered the bot with the Microsoft Bot Framework.
I have configured the Microsoft Teams channel in the Microsoft Bot Framework, and I've sideloaded my bot into Teams. My bot can receive messages from Teams users.
At present, the bot just repeats whatever it receives back to the user, but what I want it to do is post to a Microsoft Teams channel. I want it to post to a Teams channel - not a user - without being prompted first by a user. So for example given a certain condition (eg. triggered by some event such as time of day, a pull request, etc.) it posts a message in a channel.
I've read the documentation about sending proactive messages, and I gather that in order to send a message to a teams channel, the bot needs to know the "address" of the user. This information is stored in the session.message.address object, and it gets this from the current conversation. However, in my case I don't have a 'current conservation', because I don't want to just respond to a user, I want to post in a channel proactively.
So, how do I permanently set the necessary credentials/address/session-data for the Teams channel?
Things I've looked into:
Webhooks. I've configured a webhook in my Teams channel, and I can send it a message easily enough (using the webhook url) using curl. So I can send the Teams channel a simple message with just a url (no authentication required), but I'm not sure how I'd get this url into my bot.
How do we maintain different session for different users in Microsoft Bot Framework? I'm not sure that the answer here answers my question. My problem is that the bot is initiating the 'conversation', not a Teams user, so I need to be able to set the session data myself so the bot knows where to go.
App.js:
require('dotenv').config();
var restify = require('restify');
var builder = require('botbuilder');
// Setup Restify Server
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
console.log('%s listening to %s', server.name, server.url);
});
// Create chat connector for communicating with the Bot Framework Service
var connector = new builder.ChatConnector({
appId: process.env.MICROSOFT_APP_ID,
appPassword: process.env.MICROSOFT_APP_PASSWORD
});
// Listen for messages from users
server.post('/api/messages', connector.listen());
// Receive messages from the user and respond by echoing each message back (prefixed with 'You said:')
var bot = new builder.UniversalBot(connector, function (session) {
session.send("You said: %s", session.message.text);
});
For anyone who is wondering about the same for c#, here is the solution that worked for me:
var channelData = context.Activity.GetChannelData<TeamsChannelData>();
var message = Activity.CreateMessageActivity();
message.Text = "Hello World";
var conversationParameters = new ConversationParameters
{
IsGroup = true,
ChannelData = new TeamsChannelData
{
Channel = new ChannelInfo(channelData.Channel.Id),
},
Activity = (Activity) message
};
var connectorClient = new ConnectorClient(new Uri(activity.ServiceUrl));
var response = await
connectorClient.Conversations.CreateConversationAsync(conversationParameters);
Note: If you are calling this outside Bot's controller code then you need to call TrustServiceUrl on serviceUrl as shown here:
MicrosoftAppCredentials.TrustServiceUrl(serviceUrl, DateTime.MaxValue);
var connectorClient = new ConnectorClient(new Uri(serviceUrl));
Source of answer: https://github.com/OfficeDev/BotBuilder-MicrosoftTeams/issues/162
It is definitely possible. We call these proactive messages and it’s possible to proactively message both users and channels.
For the latter, see the sample at https://github.com/OfficeDev/microsoft-teams-sample-complete-node, specifically this file, ProactiveMsgToChannelDialog.ts.
To send proactive messages to channels, you need to use the Microsoft Teams SDK (as these samples do).
Last but not least, you need to add the bot to a team in order to send a message to one of the channels in the team, which requires a manifest.
Hope this works for you.. below code proactively sends the message to session before initiating the chat.
bot.on('conversationUpdate', function (message) {
if (message.membersAdded[0].id === message.address.bot.id) {
var reply = new builder.Message()
.address(message.address)
.text("Hello"");
bot.send(reply);
}
});