Developing with NodeJS code and SlackAPI to create PFBot - javascript

Recently I had a idea for a Slack Bot that would filter what a user says. I.E User says (a bad word). PFBot would see that message and change the word to "##%$&" depending on how long the word is.
Now I am fairly new to this but I knew what needed to happen.
The bot would need to read the message.
The bot would compare that message to a list of bad words.
If the bot finds one then the message is filtered. (Turning the word into "##%$".
The new message with filtered words would be reposted as that user.
I started work on it but since I am new with the Slack API and NodeJS I hit a rode block and I have no clue on how to get it working.
My first specific problem is: I can't find a way for the Bot to read a new message posted in chat.
Here is my code: https://github.com/wiredbrother/Slack-PFBot
You will be interested in the Skills/hears.js file. That is where the magic happens. Or just look here >
var fs = require('fs');
var path = require('path');
var readStream = fs.createReadStream(path.join(__dirname,
'../profanity-filter') + '/swears.txt', 'utf8');
var data = '';
readStream.on('data', function(chunk) {
data += chunk;
}).on('end', function() {
console.log(data);
});
module.exports = function(controller) {
controller.hears(['^hello$'], 'direct_message,direct_mention', function(bot, message) {
bot.reply(message, "Hi there, you're on workspace: " + message.team)
});
controller.hears([data], 'direct_message,direct_mention', function(bot, message) {
var filter = require('../profanity-filter/lib/filter.js');
filter.setReplacementMethod('grawlix');
filter.setGrawlixChars(['!', '#', '#', '$', '%', '&']);
var thing = filter.clean(data);
bot.reply(message, "The bad word is now: " + thing)
});
};
I also found a utility online for NodeJS that filters words. That is in the Profanity-Filter folder.
You would be interested in Profanity-Filter/lib/filter.js.
I would love some guidance on this as a new coder.
Thank you for any advice you can give!
~ wiredbrother

Getting new messages
To get new messages you need to enable events for your bot. Once enables your bots will automatically receive every new message, which is send to a channel that your bot user is a member of.
I have never used botkit myself, but apparently you can check the documentation here (#6) for how to enable events for the botkit.
Removing profanity
To me knowledge is not possible, to change the message from another user. There is chat.udpate, which updates a messages. But that only works for your own messages.
Instead you could delete messages form other users with chat.delete, that contains profanity (and inform the user with a direct message about his transgression).

Related

Cannot cast InputPeerChat to any kind of InputChannel

I have created a bot using Telegraf. I want that when a user sends a message, the bot will send him the previous message. So I want to take the previous post on id with Gram JS but throws this error
here is my code:
bot.on("message", async (ctx) => {
const { text, message_id } = ctx.message;
const userId = ctx.from.id;
const replyToMessage = await client.invoke(
new Api.channels.GetMessages({
channel: `${ctx.chat.id}`,
id: [message_id - 1],
})
);
console.log(1234, replyToMessage);
ctx.reply(replyToMessage);
});
I was inspecting telegram telethon api for a python task. I have some thougths about your issue.
The thing is telegram says it can not find anything with that id and channel. But I have some questions about your code.
As far as I know telegram either asks for a channel_id and channel_access_hash or the channel_username.
I am seeing that you give the telegram a channel_id and message_id ?
You should check your api docs again and try to find a method you can directly use the channel's username.
Note on that username : Telegram group or chat must be public or you must be auth, and (as far as python telethon) you must add the https:// appendix to channel_username.
I hope you can find a way out. If you further detail your question we can talk it again, I have spend plenty of time with python's telethon api.

I need help reassigning a variable in a bot menu

I am trying to build a setup menu for my bot that the server owner can use to configure the bot. The menu is triggered when the owner types =setup. I want the bot to reply with several embed messages asking the user questions in order to correctly configure the bot.
This is my first Discord.js project so I am unaware of the syntax but trying to learn. I have a constant variable called prefix assigned to = when the bot is implemented into the server.
The first prompt on the bot menu asks the user to change the prefix to anything they want. I need help understanding how to reassign my original constant variable to the new prefix they are requesting.
var PREFIX = '=';
bot.on('message', message=>{
let args = message.content.substring(PREFIX.length).split(" ");
switch(args[0]){
case 'setup':
const embed = new Discord.RichEmbed()
.setTitle('Step 1 of 1')
.setDescription('Set your Prefix')
.setColor(0xF1C40F)
message.channel.sendEmbed(embed);
//I want the user to now enter their own PREFIX and have the
//bot save their responce as the new PREFIX
break;
}
})
What I want to happen is when the user types their desired prefix, the bot will reassign prefix in the code, and delete the bots question and the users response and begin to prompt them with the next question.
depending if your bot is going to be in multiple servers with different prefixes:
If so then you need a database to save the prefix for each server and
then get it when a user sends a message from that server
If not I would use a json file to store the prefix, then have node
edit the file when it needs to change
Or look at https://discordjs.guide/keyv/ there is a great tutorial there to do what you want
You can't prompt the user to respond (from what I know), you'll need to wait for the user to write another message and analyze it.
A message is linked to a user, so when a user initiates the command to change the prefix, you want to make sure that the same user changed the prefix.
This untested but should be close to the solution you're looking for.
let prefix = '=';
let expectingResponseFrom = null;
bot.on('message', message=>{
// same user sent a response
if(expectingResponseFrom !== null && expectingResponseFrom === message.user.id){
expectingRepsonseFrom = null;
prefix = message.content.trim();
return;
}
const regex = new RegExp(`^${prefix}([^\s]+)`, 'g');
cosnt command = regex.exec(message.content)[1] || '';
switch(command){
case 'setup':
const embed = new Discord.RichEmbed()
.setTitle('Step 1 of 1')
.setDescription('Set your Prefix')
.setColor(0xF1C40F)
message.channel.sendEmbed(embed);
// memorize user who initiated a prefix change
expectingResponseFrom = message.user.id;
break;
}
})
The regex allows for a better (my opinion) way of getting the command
console.log(
(/^=([^\s]+)/g).exec("=hello should not get this"),
(/^=([^\s]+)/g).exec("="),
(/^=([^\s]+)/g).exec("= should not get this")
)
You should definitely use a database to store prefixes and other server settings, it's more efficient and stable than using a JSON file for example.
I suggest you use mongoose and/or just MongoDB if you're unsure as to what to use.

Creating a private room through a link using node.js

I've read through this:
https://socket.io/docs/rooms-and-namespaces/#
private chat with socket.io
What I'm trying to do is have a public chat on:
"/"
And a private chat on /xyz, where everyone that's using this URL can talk in.
I'll get to generating random links and figuring them out later, but first I need to figure out how to connect public users and private users to different sockets? Especially since they're doing the same thing I have no idea how to do this efficiently at all.
So firstly I have to catch a server/private URL using:
app.get("/private",function(req,res){
res.render("page");
console.log("Rendered private page"); });
The solution I've thought of first is using a custom namespace.
var namespace = io.of('/private');
namespace.on('connection',function(socket){
console.log('someone connected to private');
socket.emit('pmessage',{message:'Connected to a private chat!'});
});
But this becomes an issue with my frontend(which I know not how to manipulate since I'm very new to this). I'd basically be using duplicate code to handle the same thing, just with different subset of users.
So this:
var socket = io.connect('127.0.0.1:8090');
I need to add a new socket, right:
var private = io.connect('127.0.0.1:8090/private');
Then do I just duplicate everything? I know this is probably not the right solution. But I don't know where to turn to. Basically making everything for private instead of socket.
socket.on('message',function(data){
//Type out the message in the htmlTextField into the htmlChatContent if message was received
//Keep the other chats
if(data.message){
//From w3c:The push() method adds new items to the end of an array, and returns the new length.
//Example: ["hi","hello"] ---push("wazzzaaap")--->["hi","hello","wazzzaaap"]
messages.push(data);
//put messages into the HTML code
var html = '';
console.log("Currently in messages" + data.message);
console.log(data.username);
for(var i = 0;i<messages.length ;i++){
//Put it into a string and add a HTML defined symbol sequence for a line break
//Add username in front of it in bold
//FIXME: Currently only able to get messages[i] which is just the content
if(messages[i].username==null){
html+=messages[i].message + '<br />';
}
else{
html+='<b>'+ messages[i].username + ': </b>' + messages[i].message + '<br />';
}
}
//Add the message formatted into HTML into the chat content box
htmlChatContent.innerHTML = html;
//When sending clear the input field also
htmlTextField.value = "";
}
else{
//This means there was an error
//Put error text inside the users text box
console.log("Error");
htmlTextField.innerHTML = "There was an sending error!";
}
});
I'd appreciate guidance on how to handle randomly generated links, what I've thought of is:
Database of created links, that removes entries the second the last person leaves. However how do I program dynamic links? I can't hardcode 500 different options, right?
Do I need to add more code for the question to be better?
I'll get to generating random links and figuring them out later, but first I need to figure out how to connect public users and private users to different sockets?
No, you need one socket between the client and your server. You can then send data to just some of the aockets from your server. Socket.io got rooms for that, which basically just means that you can manage the sockets in groups and you send data to the sockets in that group easily.
I can't hardcode 500 different [sockets / links], right?
No, that would be overkill. Just let the client / server generate random urls. To make them unique you could just take the timestamp and add a random number:
const id = "" + Math.floor(Math.random() * 1000) + Date.now();
Now if you want to manage/verify clients on the http server, you could just work with dynamic urls, like:
yourserver/private/1272271737
With express thats quite easy to catch them all:
app.get("/private/:id", (req, res) => {
const { id } = req params;
// Verify the id and return the clientside code
});
But actually only the socket server needs to know the rooms id, so you could use so called "hashbang urls", they look like:
yourserver/private#127272
On the serverside it looks like if the client visits /private so you can just return the application:
app.get("/private", (req, res) => /*...*/);
But on the clientside you can get the id as:
const id = location.hash;
Now the client can join the related room:
socket.join(id);
Now when sending a message just send the room id with it:
socket.emit("msg", id, "Hi!");
On the server, you just broadcast it to that room:
io.on('connection', (socket) => {
socket.on("msg", (id, msg) => {
io.to(id).emit("msg", msg);
});
});

Discord make channel using bot

I'm making a discord bot, and I'm trying to make use of the createChannel function shown here in the documentation. For some reason, I am getting the following error:
TypeError: bot.createChannel is not a function.
My code is within a function which I pass a message to, and I have been able to create roles and add users to roles within the same function. It's just the createChannel function that's not working. Below is the relevant portions of the code.
const bot = new Discord.Client();
function makeChannel(message){
var server = message.guild;
var name = message.author.username;
server.createRole(data);
var newrole = server.roles.find("name", name);
message.author.addrole(newrole);
/* The above 3 lines all work perfectly */
bot.createChannel(server,name);
}
I have also tried bot.addChannel, and bot.ChannelCreate, since ChannelCreate.js is the name of the file which contains the code for this command. Also, I have attempted specifying channel type and assigning a callback function as well, but the main issue is the TypeError saying that this isn't a function at all. Any idea what I'm doing wrong?
Additionally, I plan to use ServerChannel.update() at some point in the future, so any advice on getting that to work once the previous problem is resolved would be greatly appreciated.
Alright, after a few days of trying things and going through the docs, I have discovered the solution. I am using a more recent version of Discord than the docs I was reading were written for. In the newer version, channels are created with a method in the server, not a client method. so, the code should be:
const bot = new Discord.Client();
function makeChannel(message){
var server = message.guild;
var name = message.author.username;
server.createChannel(name, "text");
}
The "text" value is the type of channel you are making. Can be text or voice.
I'll post a link to the most recent documentation for anyone else who encounters this problem here.
The answer should update documentation link to the GuildChannelManager which is now responsible for creating new channel.
(Example from docs)
// Create a new text channel
guild.channels.create('new-general', { reason: 'Needed a cool new channel' })
.then(console.log)
.catch(console.error);
https://discord.js.org/#/docs/main/stable/class/GuildChannelManager
#Jim Knee's I think your answer is v11, I'm new in discord.js, using Visual Studio Code's auto-code thingy. You can do all the same things except your thing must be this. If you are poor people, getting errors on doing #Jim Knee's answer, this is the place for "YOU!"
Get rid of server.createChannel(name, "text/voice");
And get it to THIS server.channels.create(name, "text/voice");
Hope I can help at least ;)
I'm just a new guy here too
I think you have not logged in with your bot.
From the docs:
const Discord = require('discord.js');
var client = new Discord.Client();
client.login('mybot#example.com', 'password', output); // you seem to be missing this
function output(error, token) {
if (error) {
console.log(`There was an error logging in: ${error}`);
return;
} else
console.log(`Logged in. Token: ${token}`);
}
Alternatively, you can also login with a token instead. See the docs for the example.

Firebase push() method shuffle the list data

Have created a chat application and we use firebase for realtime communication.
Sometimes i noticed that push() method shuffle the list data. We can see in the below image :
If we see in above image i am just trying to communicate with someone i said hello in reply user said hey, again i said i need some help then user said That's what I'm here for. What can I assist you with? in the reply but if we see in the image users reply is appearing first.
It happens intermittently that's why i didn't figure out this problem. So please someone help me out what shall i doing wrong.
var pushMessageToFB = function(){
var chatMsgRef = db.child("chatMessages").child("gr1").child("ch_usr1_usr2");
var message = {
type: "chat",
content: data.messageText,
timestamp: Date.now(),
by: user.id
};
chatMsgRef.push(message, function(err){
if (err){
console.log('error occurred while pushing message to fb : err ' + JSON.stringify(err));
}
});};
var loadChatMessages = function(){
var chatMsgRef = db.child('chatMessages').child("gr1").child("ch_usr1_usr2");
$scope.chatMessages = chatMsgRef.orderByKey().limitToLast(50);
};
Don't use Date for remote data. It will be slightly offset on every machine. Use ServerValue.TIMESTAMP which Firebase will convert to the server's Unix epoch time when the data is written. This ensures consistency of order across clients.
You didn't provide any code for how you're reading or displaying the chat messages, but since you're trying to show them in chronological order I assume your query uses orderBy("timestamp"). If you use ServerValue.TIMESTAMP when you write the message it will be guaranteed to sort in the order that it was written to the database.

Categories