Not getting a notification when trying to use real-time database communications - database

I'm trying to use web sockets to add a new notification to my app. I'm using Backand as my server, and can't seem to get a grasp on responding to the new event. Here's my server side code to send the event:
//Action: Update - After data saved and committed
function backandCallback(userInput, dbRow, parameters, userProfile) {
//Send to array of users
socket.emitUsers("new_notification",userInput, ["admins"]);
return {};
}
And my client code to receive it:
//Wait for server updates on 'items' object
Backand.on('new_notification', function (data) {
//Get the 'items' object that have changed
console.log(data);
});
But when I try to receive the event in my app code, I never see a notification of type "new_notification". Can someone please let me know what's going on?

Make sure you are using emitRole instead of emitUsers. The code above emits to a user array, but it looks like you want to send a notification to the "admins" role. Change this to emitRole() and you should be ok.

For role you want to keep it case sensitive so it will be:
socket.emitRole("items_updated",userInput, "Admin");
For users the syntax is:
socket.emitUsers("items_updated",userInput, ["user2#gmail.com","user1#gmail.com"]);

Related

Discord.js V13 -- Store persisting hidden data on the message object

I have coded a bot to send a message response to a given command, !a. I want to store additional data on the message object, so that if the user reacts to that message the bot can read the hidden data property and know the original message resulted from !a.
Ideas I had:
Create a custom property on the message object: Message.Custom_Prop
Hijack an unused property: Maybe Message.webhookId?
Store hidden text in the form of an embed or message content.
I haven't been able to get any of these to work though.
The best way that I can think of is to store an array of message IDs that were triggered by !a. Something like this:
// At the start of your script
const commandResponses = [];
// Logic for sending the command response
message.channel.send("response here").then(msg => commandResponses.push(msg.id));
// Checking whether the message was a response
if (commandResponses.includes(reaction.message.id)) {
// It's a response so do stuff here
}
(Not tested so it's possible that this won't work)

Discord JS v12: How do you get a message's content by it's ID?

I'm relatively new to discord.js, and I've started building a bot project that allows a user to create a message via command, have that message stored in a hidden channel on my private server, and then said message can be extracted through the message ID.
I have the write working and it returns the message ID of the message sent in the hidden channel, but I'm completely stumped on the get command. I've tried searching around online but every method I tried would return errors like "Cannot read property 'fetch' of undefined" or "'channel' is not defined". Here are some examples of what I tried, any help would be appreciated. Note that my args is already accurate, and "args[0]" is the first argument after the command. "COMMAND_CHANNEL" is the channel where the command is being executed while "MESSAGE_DATABASE" is the channel where the targeted message is stored.
let msgValue = channel.messages.cache.get(args[0])
client.channels.cache.get(COMMAND_CHANNEL).send(msgValue.content)
let msgValue = msg.channel.message.fetch(args[0])
.then(message => client.channels.cache.get(COMMAND_CHANNEL).send(msgValue.content))
.catch(console.error);
I even tried using node-fetch to call the discord API itself
const api = require("node-fetch")
let msgValue = api(`https://discordapp.com/api/v8/channels/${MESSAGE_DATABASE}/messages/${args[0]}`)
.then(message => client.channels.cache.get(COMMAND_CHANNEL).send(msgValue.content))
.catch(console.error);
Am I missing something or am I making some sort of mistake?
Edit: Thanks for the help! I finished my bot, it's just a little experimental bot that allows you to create secret messages that can only be viewed through their ID upon executing the command :get_secret_message <message_id>. I posted it on top.gg but it hasn't been approved yet, so in the meantime if anyone wants to mess around with it here is the link: https://discord.com/api/oauth2/authorize?client_id=800368784484466698&permissions=76800&scope=bot
List of commands:
:write_secret_message - Write a secret message, upon execution the bot will DM you the message ID.
:get_secret_message <message_id> - Get a secret message by its ID, upon execution the bot will DM you the message content.
:invite - Get the bot invite link.
NOTE: Your DMs must be turned on or the bot won't be able to DM any of the info.
My test message ID: 800372849155637290
fetch returns the result as promise so you need to use the then to access that value instead of assigning it to a variable (msgValue). Also you made a typo (channel.message -> channel.messages).
I would recommend using something like this:
msg.channel.messages
.fetch(args[0])
.then(message => {
client.channels
.fetch(COMMAND_CHANNEL)
.then(channel => channel.send(message.content))
.catch(console.error)
})
.catch(console.error)
I think you were quite close with the second attempt you posted, but you made one typo and the way you store the fetched message is off.
The typo is you wrote msg.channel.message.fetch(args[0]) but it should be msg.channel.messages.fetch(args[0]) (the typo being the missing s after message). See the messages property of a TextChannel.
Secondly, but this is only a guess really as I can't be sure since you didn't provide much of your code, when you try to fetch the message, you are doing so from the wrong channel. You are trying to fetch the message with a given ID from in the channel the command was executed from (the msg.channel). Unless this command was executed from the "MESSAGE_DATABASE" channel, you would need to fetch the message by ID from the "MESSAGE_DATABASE" channel instead of the msg.channel.
Thirdly, if you fetch a message, the response from the Promise can be used in the .then method. You tried to assign the response to a variable msgValue with let msgValue = msg.channel.message.fetch(args[0]) but that won't do what you'll expect it to do. This will actual assign the entire Promise to the variable. What I think you want to do is just use the respone from the Promise directly in the .then method.
So taking all that, please look at the snippet of code below, with inspiration taken from the MessageManager .fetch examples. Give it a try and see if it works.
// We no longer need to store the value of the fetch in a variable since that won't work as you expect it would.
// Also we're now fetching the message from the MESSAGE_DATABASE channel.
client.channels.cache.get(MESSAGE_DATABASE).fetch(args[0])
// The fetched message will be given as a parameter to the .then method.
.then(fetchedMessage => client.channels.cache.get(COMMAND_CHANNEL).send(fetchedMessage.content))
.catch(console.error);

Adding web-notification in React app similar to Alert but Not Alert

user story:
We need to alert the user when there a modification or a comment on the thing he has posted by another user.
We are new to react and we are lost in a loop about how to notify the user who is logged in on a different page (maybe his dashboard). The event is performed by another user2 where he is on a page where is commenting on the thing posted by user1.
How can we send an alert to that user1? who currently on a different page saying "there is a new comment on your post".
The issue we are thing about is: The event happens on the comment page. We can send the alert on that comment page. But how will we be able to send a notification to other users on a different page?
I know there is already present. You can take Jiira Board as an example.
Could anyone let us know how can we implement this?
One option is to use WebSockets. Whenever a user is on a page where you'd want them to be able to get a notification, open a websocket to your server:
const socket = new WebSocket('https://my-server.com/socket');
On your server, set up the socket endpoint. Whenever one user sends a message to another, on the server, for all sockets currently opened by the receiver, send a socket message informing them of the new message. Eg, on the server:
activeSockets
.filter(({ userId, socket }) => userId === receiverId)
.forEach(({ socket }) => {
socket.send('You have a new message');
});
And listen for those messages on the client:
socket.addEventListener('message', ({ data }) => {
if (data === 'You have a new message') {
alert(data);
}
});
This is, in broad terms, the industry standard for this sort of thing; it's what Stack Exchange does. It's how many websites allow the server to send data to the client without (inelegant) polling.

MEANJS: Security in SocketIO

Situation
I'm using the library SocketIO in my MEAN.JS application.
in NodeJS server controller:
var socketio = req.app.get('socketio');
socketio.sockets.emit('article.created.'+req.user._id, data);
in AngularJS client controller:
//Creating listener
Socket.on('article.created.'+Authentication.user._id, callback);
//Destroy Listener
$scope.$on('$destroy',function(){
Socket.removeListener('article.created.'+Authentication.user._id, callback);
});
Okey. Works well...
Problem
If a person (hacker or another) get the id of the user, he can create in another application a listener in the same channel and he can watch all the data that is sends to the user; for example all the notificacions...
How can I do the same thing but with more security?
Thanks!
Some time ago I stumbled upon the very same issue. Here's my solution (with minor modifications - used in production).
We will use Socket.IO namespaces to create private room for each user. Then we can emit messages (server-side) to specific rooms. In our case - only so specific user can receive them.
But to create private room for each connected user, we have to verify their identify first. We'll use simple piece of authentication middleware for that, supported by Socket.IO since its 1.0 release.
1. Authentication middleware
Since its 1.0 release, Socket.IO supports middleware. We'll use it to:
Verify connecting user identify, using JSON Web Token (see jwt-simple) he sent us as query parameter. (Note that this is just an example, there are many other ways to do this.)
Save his user id (read from the token) within socket.io connection instance, for later usage (in step 2).
Server-side code example:
var io = socketio.listen(server); // initialize the listener
io.use(function(socket, next) {
var handshake = socket.request;
var decoded;
try {
decoded = jwt.decode(handshake.query().accessToken, tokenSecret);
} catch (err) {
console.error(err);
next(new Error('Invalid token!'));
}
if (decoded) {
// everything went fine - save userId as property of given connection instance
socket.userId = decoded.userId; // save user id we just got from the token, to be used later
next();
} else {
// invalid token - terminate the connection
next(new Error('Invalid token!'));
}
});
Here's example on how to provide token when initializing the connection, client-side:
socket = io("http://stackoverflow.com/", {
query: 'accessToken=' + accessToken
});
2. Namespacing
Socket.io namespaces provide us with ability to create private room for each connected user. Then we can emit messages into specific room (so only users within it will receive them, as opposed to every connected client).
In previous step we made sure that:
Only authenticated users can connect to our Socket.IO interface.
For each connected client, we saved user id as property of socket.io connection instance (socket.userId).
All that's left to do is joining proper room upon each connection, with name equal to user id of freshly connected client.
io.on('connection', function(socket){
socket.join(socket.userId); // "userId" saved during authentication
// ...
});
Now, we can emit targeted messages that only this user will receive:
io.in(req.user._id).emit('article.created', data); // we can safely drop req.user._id from event name itself

Act upon response of AutoSync insert operation

I have a Store with autosync:true.
When loading the store, I'm getting complete models:
[{"id":11,"active":true,"name":"ABC","sens":7,"details":119,"type":13,"acl":false,"create":true,"delete":true,"owner":"alexander","members":"gustave\njerome"}]
When syncing a new model to the server, I'll send it with "id":0, so the server knows it has to create a new one. The server will then respond {"success":true,"data":[12],"debug":[]}, where 12 is the id of the newly created entry.
Now I have to add a callback function for the autoSync operation to patch the ids I receive back into the store.
If I had synced manually, this would have been easy:
Ext.getStore("RightsStore").sync({
success:function() {
}
})
But how can I get a special success or a callback function for insert syncs into a store that works with autoSync?
If the server sent {"success":true, "data"[{"id":12, ....}]} then you do not need to do anything. Best is if server sends back complete records it received for CRUD operation with the updated data (in same order). Ext takes care of the rest.
If you're unable to change the server output as #Saki had mentioned, you can just listen to the load event and update the records with the new id there.
store.on('load', me.loaded, me);
loaded: function(store, records) {
}
More details here - http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.data.Store-event-load

Resources