How to send a message to all subscribed users with kik bot - node.js

I'm just a beginner trying to learn how to write a bot for kik.
I'm trying to write it with the node js framework that kik has provided.
I want to send a message to all subscribed users of the bot; I found this in their docs:
bot.send(Bot.Message.text('Hey, nice to meet you!'), 'a.username');
but I'm confused as to how they get the username of the subscribed user. I tried using bot.getUserProfile.username, but it seems to be undefined.
Thanks for any help! Also, any tips on how this bot works would be appreciated! I have no web development experience; why does this bot have to be on a server?

First of all, if you want to send a blast to all of your users, I'd recommend using the broadcast API, which allows you to send messages by batches of 100 (instead of 25 for the regular send() API).
You can use the broadcast API like this:
bot.broadcast(Bot.Message.text('some message'), ['username1', 'username2']);
Documentation for this method can be found here.
As for sending messages to all of your users, you will need to have a list of usernames somewhere (in a database, for example). At the moment, Kik does not provide a way to get your list of subscribers.
Something like this would work:
bot.use((msg, next) => {
let username = msg.from; // Find the username from the incoming message
registerInDatabase(username); // Save it somewhere
next(); // Keep processing the message
});
You will need to make sure that this is placed before you declare any other handler (such as bot.onTextMessage(), for instance).

Related

Better strategy for bot posting messages to multiple channels with DiscordJs

I am trying to execute bot functions from a node express server and it seems the best option is the DiscordJs package (correct me if I'm wrong for this use-case). For example, a user takes some action on my web application that would grant them a role to access different channels. The DiscordJs docs all seem to focus on actions like this being prompted from the discord server through bot commands or detecting changes with members.
I would like to execute bot functions from my express server by instantiating one client, logging that client in, and executing functions from the server. Something to the effect of
const client = new Discord.Client({intents: [Discord.Intents.FLAGS.GUILDS, "GUILD_MESSAGES", "GUILD_MEMBERS"]});
client.on("<some event on express server>", (event) =>{
//event actions
});
client.login(token)
Is DiscordJs the right tool for this use case? Should I be using something other than Discord.Client to do this? Any suggestions/input would be appreciated.
DiscordJs is a great package, I have a fair amount of experience using it.
For your use case I think it would work great.
client.on(event, function) will only take Discord events as event arguments. These are listed here:
https://discord.js.org/#/docs/discord.js/stable/class/Client
You could however use events from your web server using something similar to below
const client = new Discord.Client({intents: [Discord.Intents.FLAGS.GUILDS, "GUILD_MESSAGES", "GUILD_MEMBERS"]});
yourWebServer.on("yourEvent", (event) => {
client.doSomething()
}
client.login(token)
The main problem to tackle if you wish to use the discord client in this way is identifying the Guild/Message/Role/Whatever you want to change.
Normally, discord bots react to messages so they have access to a lot of data very quickly. In the below example, the bot can get a great deal of information from the message data alone, like the author, the guild it was posted in, the roles in that guild etc. You can see a list of properties here: https://discord.js.org/#/docs/discord.js/stable/class/Message
const client = new Discord.Client({intents: [Discord.Intents.FLAGS.GUILDS, "GUILD_MESSAGES", "GUILD_MEMBERS"]});
client.on("messageCreate", (message) => {
client.doSomething()
});
client.login(token)
If you plan to use this discord bot on just 1 server messing around with your friends or whatever (i do this a lot), you can find your server's Guild ID and hardcode it somewhere into your bot. You can then fetch all roles/messages/users/whatever as you wish.
For any wider usage you'd have to get the context from somewhere else, e.g. inputting ids on a form on your web server.
Have a good read of the discord.js documentation, its very well made in my opinion. Get an idea of what information you want to access, and how you can access it. It will then be easier to determine what context you need to give the bot to find this information.
For those wondering how to use discordjs client commands outside of an event listener it is possible but requires diligent use of async/await. Check this thread for more insight https://github.com/discordjs/discord.js/issues/3100

how does users.watch (in gmail google api) listen for notifications?

I am confused as to how should the watch feature in the gmail API be implemented to recieve the push notificatons inside a node.js script. Should I call the method inside an infinite loop or something so that it doesn't stop listening for notifications for email once after the call is made?
Here's the sample code that I've written in node.js:
const getEmailNotification = () => {
return new Promise(async (resolve, reject) => {
try{
let auth = await authenticate();
const gmail = google.gmail({version: 'v1', auth});
await gmail.users.stop({
userId: '<email id>'
});
let watchResponse = await gmail.users.watch({
userId: '<email id>',
labelIds: ['INBOX'],
topicName: 'projects/<projectName>/topics/<topicName>'
})
return resolve(watchResponse);
} catch(err){
return reject(`Some error occurred`);
}
})
Thank you!
Summary
To receive push notifications through PUB/SUB you need to create a web-hook to receive them. What does this mean? You need a WEB application or any kind of service that exposes a URL where notifications can be received.
As stated in the Push subscription documentation:
The Pub/Sub server sends each message as an HTTPS request to the subscriber application at a pre-configured endpoint.
The endpoint acknowledges the message by returning an HTTP success status code. A non-success response indicates that the message should be resent.
Setup a channel for watch the notifications could be summarized in the following steps (the documentation you refer to indicates them):
Select/Create a project within the Google Cloud Console.
Create a new PUB/SUB topic
Create a subscription (PUSH) for that topic.
Add the necessary permissions, in this case add gmail-api-push#system.gserviceaccount.com as Pub/Sub Publisher.
Indicate what types of mail you want it to listen for via Users.watch() method (which is what you are doing in your script).
Example
I give you an example using Apps Script (it is an easy way to visualize it, but this could be achieved from any kind of WEB application, as you are using Node.js I suppose that you are familiarized with Express.js or related frameworks).
First I created a new Google Apps Script project, this will be my web-hook. Basically I want it to make a log of all HTTP/POST requests inside a Google Doc that I have previously created. For it I use the doPost() equal to app.post() in Express. If you want to know more about how Apps Script works, you can visit this link), but this is not the main topic.
Code.gs
const doPost = (e) => {
const doc = DocumentApp.openById(<DOC_ID>)
doc.getBody().appendParagraph(JSON.stringify(e, null, 2))
}
Later I made a new implementation as a Web App where I say that it is accessible by anyone, I write down the URL for later. This will be similar to deploying your Node.js application to the internet.
I select a project in the Cloud Console, as indicated in the Prerequisites of Cloud Pub/Sub.
Inside this project, I create a new topic that I call GmailAPIPush. After, click in Add Main (in the right bar of the Topics section ) and add gmail-api-push#system.gserviceaccount.com with the Pub/Sub Publisher role. This is a requirement that grants Gmail privileges to publish notification.
In the same project, I create a Subscription. I tell it to be of the Push type and add the URL of the Web App that I have previously created.
This is the most critical part and makes the difference of how you want your application to work. If you want to know which type of subscription best suits your needs (PUSH or PULL), you have a detailed documentation that will help you choose between these two types.
Finally we are left with the simplest part, configuring the Gmail account to send updates on the mailbox. I am going to do this from Apps Script, but it is exactly the same as with Node.
const watchUserGmail = () => {
const request = {
'labelIds': ['INBOX'],
'topicName': 'projects/my_project_name/topics/GmailAPIPush'
}
Gmail.Users.watch(request, 'me')
}
Once the function is executed, I send a test message, and voila, the notification appears in my document.
Returning to the case that you expose, I am going to try to explain it with a metaphor. Imagine you have a mailbox, and you are waiting for a very important letter. As you are nervous, you go every 5 minutes to check if the letter has arrived (similar to what you propose with setInterval), that makes that most of the times that you go to check your mailbox, there is nothing new. However, you train your dog to bark (push notification) every time the mailman comes, so you only go to check your mailbox when you know you have new letters.

Websocket vs SSE to implement a real time friend invitation system on React/Node

I would like to implement a system that allows users to add each other as friends and share data between them. I have gotten the authentication done and currently researching ways to do this real time. This project of mine is purely a learning experience so I am looking for many ways to perform this task to grow my knowledge.
I have experience using Websockets on a previous project and it was easy to use. Websockets seems like the best solution to my problem as it allows the user to send and receive invites through the open socket. However I have also learnt that the downside would be a long open socket connection that might be potentially performance taxing(?) Since I'm only sending/receiving information only when an invite is sent/received, websockets might be overutilized for a simple function.
At the same time I would like to learn about new technologies and I found out about Server Sent Events that would be less performance heavy(?) Using SSE would be much efficient as it only sends HTTP requests to the clients/server whenever the user send the invite.
Please correct me if I'm wrong for what I typed out above as this is what I gathered through my reading online. So now I'm having a hard time understanding whether SSE is better than websocket for my project. If there are other technologies please do let me know too! Thank you
how you doing ?
The best advise would be always to use websocket in this context, cuz your project can grow and need some feature that would be better using websocket
But you got another options, one of the is Firebase, Yes, FIREBASE!
You can do a nice reactive application with firebase, becouse the its observers update data in realtime, just like the websockets do.
But here go some cons and pros.
Websocket: Can make your project escalable, its more complete, you can use it in any context, BUT: is hard to implement and takes more time to be learned and understood.
Firebase, Easy and fast to implement, you can do a chat in 20 minuts, and surelly would help you with your problem, There is Firestore and Reatime database.. even the firestore updates in realtime.. BUT: Firebase costs in a big project can be expensive, i dont think is a good option for a big project.
Thats it.. the better options to do a real time data application to me.
A little bit more about. Firebase vs Websocket
https://ably.com/compare/firebase-vs-socketio
to send a friend invitation, you just send an API request. WebSocket is used for real time communication. From react.js, get the email and send the email to the server
export const sendFriendInvitation = async (data) => {
try {
return axios.post("/friend-invitation", data);
} catch (exception) {
console.error(error)
}
};
On node.js side, write a controller to control this request:
const invitationRequest = async (req, res) => {
// get the email
const { targetMail } = req.body;
// write code to handle that same person is not sending req to himself
// get the details of user who sent the email
const targetUser = await User.findOne({
mail: targetMail.toLowerCase(),
});
if (!targetUser) {
return res
.status(404)
.send("send error message");
}
// you should have Invitations model
// check if invitation already sent.
// check if the user we would like to invite is our friend
// now create a new invitation
// if invitation has been successfully created, update the user's friend
return res.status(201).send("Invitation has been sent");
};

Twit listen for mentions, but ignore replies

I am developing a twitter bot. One main feature is that it needs to listen for when it gets mentioned. I am doing that with this code:
var stream = T.stream('statuses/filter', { track: #ExampleName });
stream.on('tweet', tweeted);
However, the function tweeted still gets called when one of #ExampleName's tweets gets responded to.
This is because twitter automatically mentions the user you respond to when replying.
Is there anyway I could make it ignore responses, and only listen for mentions?
The legacy Twitter streaming API does not provide for more complex queries when using the track keyword, so you would have to do that filtering out yourself inside the tweeted function to decide if this was a mention or a response / reply.
In the new v2 Filtered Stream, you could create a rule that explicitly excludes replies to Tweets from the user. For example in your case you could have a rule of #ExampleName -is:reply. At the moment, the twit library does not support v2, but there are some alternatives, as well as sample code.

"Bind" socket to user

I'm fairly new to sockets and wanted to give an existing application a few realtime elements, like notifications. I'm using SailsJS (and Passport with local strat) and wanted a service which can be called like
Notification.send(userID, message);
This would also be a pretty cool way for all other kinds of realtime events (private messages, ...). But what I need to know is how to "bind" a socket to a UserID.
Any ideas or articles (couldn't find anything on Google - probably because I don't know what exactly to search for...)? Thanks.
Assuming you have the pubsub hook enabled (it's enabled as long as you don't see pubsub: false) in your .sailsrc, You can have a client subscribe to their own user model like this so they will receive any notifications sent to their userId:
User.findOne(userId).then(function (me) {
User.subscribe(req.socket, me, 'message');
})
Then you can call this to send notifications to a specific user in controllers:
User.message(recieverUserId, {type: "message", data: notification});
Just change type to whatever is relevant like type: "new Match" and send the appropriate data.
Edit: basically, .message() is the sails pubsub library's way of sending notifications to the subscribed Model. you could also pass an array of users into User.subscribe

Resources