Restrict slash command usage to app channel - slack

I created a slack app using botkit / node.js / express server.
My method:
controller.on('slash_command', function(bot, message) { SOME_LOGIC }
listens for all slash commands in every single channel. Now, my bot (slack app) has it's own direct channel. I want my slash command to only listen for slash commands in that particular channel. Is it possible to restrict slash commands liKE this? What would it look like?
I can't seem to find a unique identifier for speaking directly with slack app bot.

Yes, that is possible.
In general slash commands will work in any channel / conversation and there is no option in the Slack API to restrict them to specific conversations. But, you can add the appropriate functionality to your app, so it only reacts to the command coming from the app channel. Here is how:
1. Detecting the right conversation
Every slash command request from Slack includes the channel ID from the conversation it was issues in and the user ID from the corresponding user. (see below for an example slash command). Your app just needs to look for the channel ID corresponding to the app channel and react accordingly.
Here is an example of a slash command (from the official documentation)
token=gIkuvaNzQIHg97ATvDxqgjtO
&team_id=T0001
&team_domain=example
&enterprise_id=E0001
&enterprise_name=Globular%20Construct%20Inc
&channel_id=C2147483705
&channel_name=test
&user_id=U2147483697
&user_name=Steve
&command=/weather
&text=94070
&response_url=https://hooks.slack.com/commands/1234/5678
&trigger_id=13345224609.738474920.8088930838d88f008e0
To get the channel ID corresponding with the current user you can call conversations.list with types set to IM, which will give you all direct message channels with their channel IDs of your app. The one where user equals the user ID from the current slash request is the correct one.
Here is an example response from channels.list for direct messages:
{
"ok": true,
"channels": [
{
"id": "D0G9QPY56",
"created": 1449709280,
"is_im": true,
"is_org_shared": false,
"user": "USLACKBOT",
"is_user_deleted": false,
"priority": 0
},
{
"id": "D1KL59A72",
"created": 1466692204,
"is_im": true,
"is_org_shared": false,
"user": "U0G9QF9C6",
"is_user_deleted": false,
"priority": 0
}
}
2. Responding to other conversations
In addition you will need to also respond to slash command request from other conversations or you will get a timeout error on Slack.
For those you can respond with an empty body and HTTP code 200, which will not create any output on Slack.
Alternatively, you could respond with a short message explaining to the user that he should use your slash command in the proper channel. (I would recommend this option since it is more user friendly)

Related

Perform action on seen/unseen messages with socket.io

What is the best practice to handle seen/unseen messages in a chat room application based on Nodejs/SocketIO/React.
Consider User1 sends a message to a room. If another user has seen that message, notify all users that the state of message has been seen.
In my opinion using message brokers can be the better solution instead socket. I actually think that socket should only handle chat messages that are synchronously. but for seen/unseen status I prefer message brokers that are asynchronous. Are there any solutions or best practice in large scale applications?
It's unclear what you have currently tried, meaning that I can only advise solutions in order to achieve your aim.
To firstly identify that a message was seen, IntersectionObserver is an inbuilt API that detects when an element has entered the viewport, meaning that it is visible, therefore; obviously seen. I have added comments in the code below where you should add a function to call to the server that the message was seen, however, that's up to you to implement.
const observer = new window.IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
// Send a message to the server that the user has viewed the message.
// Eg. socket.emit('read-message', message.id)
return
}
}, {
root: null,
threshold: 0.1,
})
observer.observe(document.getElementById(message.id));
Additionally, there's no need to use message broker, as socket.io can handle simple interactions such as this.
You then need to send a message to the server that denotes the specified message ID was seen, then broadcast to every other client that the state was changed, and update it to read - if that's needed.

How do I get the "true" online status of a user via the slack api?

I'm working on a project where tickets are assigned to users based on their presence in Slack. This presence can be Active or Away, but one can also manually set this presence to Away. A clever user can manually set his or her presence and avoid being assigned work. This is something I would like to avoid.
For the moment I use the users.getPresence method which works fine, but I would like to retrieve the "true" presence of users.
The users.getPresence documentation page has the following info:
If you are requesting presence information for the authed user, this method returns the current presence, along with details on how it was calculated:
{
"ok": true,
"presence": "active",
"online": true,
"auto_away": false,
"manual_away": false,
"connection_count": 1,
"last_activity": 1419027078
}
This method provides information regarding the connection count and if a user has manually changed his status to Away. My assumption is that, using this information, I can see if a user is online but he is being sneaky.
However, I have no idea how to retrieve this information. What is this 'authed' user and can you only get this information for this user?
Furthermore, I accidentally retrieved this 'extended' getPresence data when I send a request to my app using an email address as input, instead of a Slack ID. However, the response is always the same:
{
"ok": true,
"presence": "away",
"online": false,
"auto_away": false,
"manual_away": false,
"connection_count": 0
}
It doesn't matter if I'm active or manually away, the response is always the same.
Has anybody here figured out how this 'extended' getPresence works? I would love to know you did it.
If anybody has an idea on how to retrieve the "true" online status in Slack, please let me know :D
Authed user is the user that allowed their account data to be accessed, it is a breach of privacy for the API to allow an application to have access to user's "true" online status when they obviously do not want it known and have not consented to it.

How to filter data by channel in config file of sync gate way in Couchbase?

I connected to sync gate way via Api ,but I don't know how to filter some data and use them in my laravel project.
You are not filtering by channel in the syncgateway config, the filtering is the outcome of the sync-function, but it is more of a passive result of attaching a channel to a document.
I have no idea which version you are using because your question lacks it, however configuration is pretty straight forward.
you basically have 2 options of attaching a channel to a document, the second is overriding the first:
1. don't have any sync function in the config file and just rely on a "channels" property, that property will make the document sync to the appropriate channels.
for example:
{ "name": "Duke", "lastName": "Nukem", "channels": ["DukeNukem","Duke"] }
2. Have a sync function in the config file:
For the document:
{ "name": "Duke", "lastName": "Nukem" }
you might have that sync function that will do the same:
function(doc, oldDoc){
if (doc.name && doc.lastName) {
channel(doc.name);
channel(doc.name + doc.lastName);
}
}
please note that you will have to grant permission to the user to able to see a channel.
in the client side you would need that user with the permission, and if you are not filtering for a channel - you will get the docs whenever you sync.
please read more here
Here is a Swift example on the client side on how to use the "channels" to route data:
let manager = CBLManager()
let database = try! manager.databaseNamed(dbName)
let pull = self.database.createPullReplication(url)
// We need to sync channels
pull.channels = ["somechannels"]
pull.start()
A concrete example on a Store management application, every documents belong to a Store would be saved with channels contain the storeID.
On the client side, when syncing we will put the storeID inside channels so that the sync will get only the documents belong to that Store. (we are using the default sync function)
Note that, there are security concern that you need to take into consideration, read more here.

Slack messages incoming web hooks as unique message not continued

I am hitting an API to return stats of some websites, I analyse the returned values and add some of the sites to an array.
I then construct a slack message and add the array of sites to the fields section like this;
"attachments": [
{
"fallback": "",
"color": "#E50000",
"author_name": "title",
"title": "metrics recorded",
"title_link": "https://mor47992.live.dynatrace.com/#dashboard;id=cc832197-3b50-489e-b2cc-afda34ab6018;gtf=l_7_DAYS",
"text": "more title info",
"fields": sites,
"ts": Date.now() / 1000 | 0
}
]
This is all in a lambda which is triggered every 5 minutes, the first message comes through fine.
however subsequent messages just append to the fields section of the original message so it looks like I have delivered duplicate content in the message. is there a way to force each hit to the incoming web hook to post as a brand new message to slack?
here is an example of a followup message, notice the duplicate content.
No. Its a "feature" of Slack that is will automatically combine multiple message from the same user / bot without restating the user name if they are send within a short time frame.
To separate the attachments in your case would suggest to add an introduction text. Either via text property of the message (on same level than attachments property). Or by adding a pretext to each attachment.

Parse Background Job can send a message to all users currently logged in?

I am new to Parse and I want to know if there is a way to schedule a Background job that starts every 3 minutes and sends a message (an integer or something) to all users that at that moment are logged in. I could not find any help here reading the guide. I hope someone can help me here.
I was in need to push information for all logged in users in several apps which were built with Parse.com.
None of the solutions introduced earlier by Emilio, because we were in need to trigger some live event for logged users only.
So we decided to work with PubNub within CloudCode in Parse : http://www.pubnub.com/blog/realtime-collaboration-sync-parse-api-pubnub/
Our strategy is to open a "channel" available for all users, and if a user is active (logged in), we are pushing to this dedicated "channel" some information which are triggered by the app, and create some new events or call to action.
This is a sample code to send information to a dedicated channel :
Parse.Cloud.define("sendPubNubMessage", function(request, response) {
var message = JSON.stringify(request.params.message);
var PubNubUrl;
var PubNubKeys;
Parse.Config.get().then(function(config) {
PubNubKeys = config.get('PubNubkeys');
}).then(function() {
PubNubUrl = 'https://pubsub.pubnub.com/publish/';
PubNubUrl+= PubNubKeys.Publish_Key + '/';
PubNubUrl+= PubNubKeys.Subscribe_Key + '/0/';
PubNubUrl+= request.params.channel +'/0/';
PubNubUrl+= message;
return Parse.Cloud.httpRequest({
url: PubNubUrl,
headers: {
'Content-Type': 'application/json;charset=utf-8'
}
}).then(function(httpResponse) {
return httpResponse;
});
}).then(function(httpResponse) {
response.success(httpResponse.text);
}, function(error) {
response.error(error);
});
});
This is an another sample code used to send a message to a dedicated channel once something was changed on a specific class :
Parse.Cloud.afterSave("your_class", function(request, response) {
if (!request.object.existed()) {
Parse.Cloud.run('sendPubNubMessage', {
'message': JSON.stringify({
'collection': 'sample',
'objectId': request.object.id
}),
'channel' : 'all' // could be request.object.get('user').id
});
}
});
#Toucouleur is right in suggesting PubNub for your Parse project. PubNub acts essentially like an open socket between client and server so that the sever can send messages to clients and vice versa. There are 70+ SDKs supported, including one here for Win Phone.
One approach for your problem would be to Subscribe all users to a Channel when they log in, and Unsubscribe from that Channel when they exit the app or timeout.
When you want to send a message you can publish to a Channel and all users Subscribed will receive that message in < 1/4 second. PubNub makes sending those messages as Push Notifications really simple as well.
Another feature you may find useful is "Presence" which can give you realtime information about who is currently Subscribed to your "Channel".
If you think a code sample would help let me know!
Here's a few ideas I came up with.
Send a push notification to all users, but don't add an alert text. No alert will show for users who have the app closed and you can handle the alert in the App Delegate. Disadvantage: Uses a lot of push notifications, and not all of them are going to be used.
When the app comes to foreground, add a flag to the PFInstallation object that specifies the user is online, when it goes to the background, set the flag to false. Send a push notification to the installations that have the flag set to true. Disadvantages: If the app crashes, you would be sending notifications to users that are not online. Updating the user twice per session can increase your Parse request count.
Add a new property to the PFInstallation object where you store the last time a user did something, you can also set it on a timer of 30s/1m while the app is open. Send a push notification to users that have been active in the last 30s/1m. Disadvantage: Updating the PFInstallation every 30 seconds might cause an increase on your Parse request count. More accuracy (smaller interval) means more requests. The longer the session length of your users, the more requests you will use.

Resources