Slack `member_joined_channel` - how to check if my bot was invited? - slack

I want to send a message to any public channel that my bot gets added to. I notice there's the member_joined_channel event as documentated here, however I'm not sure how to figure out when to determine if my bot was the invited member. I know there's the user property, but I don't want to hardcode my bot's user ID.

I'm not familiar with the slack API, but i found this endpoint :
https://api.slack.com/types/conversation
In the response, you have a flag is_member which contains what you need I think :
is_member indicates whether the user, bot user or Slack app associated
with the token making the API call is itself a member of the
conversation.
EDIT:
then, you can retreive the list of public channel and have this flag on every channel accessible :
https://api.slack.com/methods/conversations.list

If you are writing a WebSocket-based "RTM" bot, you can listen for the channel_joined event, which is sent only for your own user/bot.
For the more typical Webhook-based bot, the best choice is to listen for the member_joined_channel event and compare the user field if you want an event-based implementation. Hardcoding or otherwise storing your bot's user id is a necessity.
Otherwise, as suggested in the previous answer, you can periodically query all conversations with the conversations.list method and check if you have become a member using the is_member field.
In case one of these methods does not provide the is_private field that you need to determine whether a channel is public, you can use the conversations.info method, which returns a channel object with the is_private field.

Coversation info is your friend https://api.slack.com/methods/conversations.info

Related

Is conversation Id in slack immutable?

I need to send messages to channels. Documentation give advice to receive all channels, pick you channel by name and after all send message by conversationId.
I want to cache the value of conversation id. But I want to be sure it won't be changed.
Documentation says
Recently we began preserving the channel ID of channels converted from
public to private.
So we can conclude, that it is immutable now
https://api.slack.com/changelog/2018-09-more-reasons-to-be-a-conversations-api-convert

How to automatically add group members to slack channel that fits a certain REGEX

Whenever there is a channel with the name that matches a certain regex, we want to add a certain group of members to these channel automatically. For example, if a new slack channel with the name that matches the regex INC-.* is created, slack group #incidentmembers will be added to that new slack channel automatically
Is there a way to configure this in Slack?
There's no native way to do this in Slack, but you could build something using the public APIs. Specifically you would
Listen to the channel_created event which fires when a public channel is created, which you can then regex as you see fit.
Grab the membership of the relevant User Group using usergroups.users.list (if the membership is static you could probably skip this)
Use conversations.invite to add the users to the channel
One limitation of this approach is that you won't get channel_created events for private channels. There's no way around this I'm afraid.

Get list of channels a user is a member of

Writing a slack bot and I would like to be able to get a list of all the channels my bot is a member of. One way to do this is to call https://slack.com/api/channels.list, get a (potentially large) list of all channels and then search for the channels that the current (bot) user is a member of. This works fine, but seems very heavy handed.
Is there a better way? To get just the channels that a given user is a member of?
I think users.conversations is what you're looking for. Without additional params it will return all public channels the calling user is a member of.
No, there is no shorter way to get this information.
Actually, Slack recommends to use the new conversations methods for this task, since the members property in all other methods, e.g. channels.list has recently been changed to only return a truncated user list. See here for details.
With conversations you have to make an additional call per channel to get all channels a user is a member of. However it will work with all types of channels (e.g. public channels, private channels) at the same time.
The basic approach is:
Get the list of all conversations from conversations.list
Get the list of members per conversation form conversations.members.
So if you want your Slack app to be future proof and also work with large number of users better use the conversations methods for your task.
FYI you can now list user channels/conversations using:
https://api.slack.com/methods/users.conversations

Google Calendar Watch and Events working together

I am creating a Node/Express Webapp that would mirror a user's calendar. It would get a notification for every change in the users calendar, and would update the DB with the latest of that user's calendar.
Lets assume that we want to monitor john.doe#gmail.com. Kindly tell me if this is the best (and only) way to do it:
Set up for Push notification - While doing so, we provide (amongst other fields):
token - A plain-text that would be echoed back. This is where I can put something like 'calOwner=john.doe#gmail.com'
id - A UUID channel id
Upon every change, my webhook will get a push notification that would contain:
token : calOwner=john.doe#gmail.com
id : the channelId - I dont understand if this field alone can be used to trace this notification message back to john.doe#gmail.com
Now that I know john.doe#gmail.com has changed, I would do a list with a synchToken. This will return me the change in john's calendar since last synch
What baffles me here is that the seemingly important fields channelId and resourceId (which appears as x-goog-resource-id in the push notification header) are useless, and the only field that ties the push message to list is an optional plain-text field token .
Kindly tell me if this is the only way to track a user's calendar.
UPDATE
Thanks #KENdi for the answer.
My struggle was with the point that simply looking at a push notification message, there is no way to trace it back to john.doe#gmail.com . I now understand why such is the case, that a push notification does not contain the calendarId, but the resourceId instead (which, in plain terms is the event object). It is so because an event can be associated with multiple calendars, and hence multiple calendarIds. Hence, it is the subscriber's responsibility to maintain association of the channel to the calendarId that he had used to create the channel at the first place.
Yes, you are correct, you need the calendar push notification, to notify you about all the changes happened in the Google Calendar.
The purpose of X-Goog-Resource-ID is an opaque value that identifies the watched resource. And this ID is stable across API versions.
Check this SO question to know more about the purpose of X-Goog-Resource-Id.

Filtering socket.io subscriptions

Imagine I have a User model and also a Message model. User has many messages.
Then in the client I do a:
io.socket.get('/user/2/messages'....
I get all my user messages and there is no problem trying to get someones else messages because I have a policy for that. Good.
I want to listen if the user has new messages, if I do a:
io.socket.on('message')
I get every message created, mine or not mine.
So: Can I listen just for MY messages? AKA listen for associated messages but not all of them.
Maybe using a policy or something for just that. Because even if there is a way to listen to them, anyone can modify the client to listen to what he wants to, I need to filter all of that.
Yes, you can. The trick is to listen for user events with the "addedTo" verb, rather than listening directly for message creation. The code would be something like:
io.socket.on('user', function(msg) {
if (msg.verb == 'addedTo' && msg.attribute == 'messages') {
// A new message was added to the user's "messages" collection
var messageId = msg.addedId
// From here you can request /message/[messageId] to get the
// message details if you need them
}
});
More info on the .publishAdd() doc page.
Note that only the ID of the added message is given; you may find you want the whole thing. You can handle that by either making a separate request for the new message, or overriding publishAdd as is suggested in this answer.
The only catch here is to make sure you're limiting who gets subscribed to those user events. It sounds like you have a policy in place that prevents users from accessing /user/:id/messages for other users. You'll want want preventing them from accessing /user/:id for other users as well (at least via sockets), since they will be subscribed to any user they access that way.
If this is undesirable--that is, if you'd like people to be able to hit those routes--then an alternative would be to use the autoSubscribe model property to restrict the automatic subscription that blueprints normally do. autoSubscribe is normally set to true, which means that any time a socket request is made for a model, the requesting socket will be subscribed to all events for that model instance. You can instead set it to an array of contexts that should be subscribed to. Contexts are specific events you're interested in, like update or destroy (more about contexts in the docs). Finally, you can set autoSubscribe to false to restrict subscription to that model entirely. Then you can just subscribe manually with .subscribe() whenever you want to listen for events.
You can see some examples of contexts and autoSubscribe in action in the sailsChat sample app.

Resources