Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for slack Events api #66

Closed
wants to merge 10 commits into from
Closed

Conversation

ewingrj
Copy link
Contributor

@ewingrj ewingrj commented Jan 13, 2018

This PR updates the bridge to use slacks events api & a bot user. This allows bridging of as many channels as you would like with only 1 slack integration per slack team/workspace.

This is fully backwards compatible with the incoming/outgoing webhooks.

Also improvea slack -> matrix file uploads

- abstracted out a BaseSlackHandler class which the SlackEventHandler
& SlackHookHandler extend.
- fix bug with room linking
- enable slack msg transformations in SlackEventHandler
- provide better file bridging support from slack -> matrix
Copy link
Contributor

@erdnaxeli erdnaxeli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great PR, thanks a lot!

I need to test it, but it looks good.

README.md Outdated

### Recommended

1. add a custom app to your slack team/workspace by visiting https://api.slack.com/apps
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'Add' with a capital.

README.md Outdated

Note: media uploaded to matrix is currently not permissioned, and anyone with the link
can access the file. In order to make slack files visible to matrix users, this bridge
will set make the slack file visible to anyone with the url (including files in private channels).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'will make' no?

README.md Outdated
the channel. Unfortunately, it is not easily obtained from the Slack UI. The
easiest way to do this is to send a message from Slack to the bridge; the
bridge will log the channel ID as part of the unrecognised message output.
You can then take note of the `channel_id` field.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually the channel ID is in the channel URL: https://XXX.slack.com/messages/<channel id>/.

README.md Outdated

- files:write:user

Note: media uploaded to matrix is currently not permissioned, and anyone with the link
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This note is confusing. The 'files:write:user' permission allow the bot to upload file to slack right? But in your note you talk about the other way.

},
json: true,
}).then((response) => {
if (!response.team) return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not Promise.resolve()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's no need, since we're already in a promise

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, but your are doing it line 447.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops. removed.

*
* @param {Object} params The event request emitted.
* @param {string} params.event.user Slack user ID of user sending the message.
// * @param {string} params.user_name Slack user name of the user sending the message.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's not needed anymore, just remove it.

var room = this._main.getRoomBySlackChannelId(params.event.channel);
if (!room) throw new UnknownChannel(params.event.channel);

if (params.event.subtype === 'bot_message' && params.event.bot_id === room.getSlackBotId()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is not slack_bot_token, lookupAndSetUserInfo will never set slack_bot_id, so this condition is always true, and I'm afraid we have a loop.

The condition should be something like:

params.event.subtype === 'bot_message' && (!room.getSlackBotToken || params.event.bot_id === room.getSlackBotId())

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will let you answer, but if I understand your code we got here only if we are using the Event API, so slack_bot_id is defined.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, the SlackEventHandler should only be used if slack_bot_id is set. I added your check anyways, as it should save some loops when incorrectly setup

}
return undefined;
}) :
Promise.resolve(display_name);
Copy link
Contributor

@erdnaxeli erdnaxeli Jan 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a one liner anymore, please use

var getDisplayName;
if (!display_name) {
    
}
else {
    result = Promise.resolve(display_name);
}


return getDisplayName.then(display_name => {
if (!display_name) return Promise.resolve();
if (this._display_name === display_name) return Promise.resolve();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can do both with one if.

@@ -53,9 +59,15 @@ SlackHookHandler.prototype.startAndListen = function(port, tls_config) {
});

request.on("end", () => {
var params = qs.parse(body);
var isEvent = request.headers['content-type'] === 'application/json' && request.method === 'POST';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If isEvent is true, this means it's an event from the Event API right? Could you just add a comment please?

@ewingrj
Copy link
Contributor Author

ewingrj commented Jan 16, 2018

Thanks for the 2nd pair of eyes and catching all the things I forgot to cleanup :)

sendMessageParams.body.as_user = false;
sendMessageParams.body.channel = this._slack_channel_id;
}

sendMessageParams.body.username = user.getDisplaynameForRoom(message.room_id);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I am wondering if this will still work with a bot user. See here the part about "Authoring messages": https://api.slack.com/changelog/2017-09-the-one-about-usernames#changing.

If I am correct, a bot user cannot change the username anymore :(

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did some reading and this page seemed to suggest you could: https://api.slack.com/methods/chat.postMessage (I have no idea just providing links 😆 )

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, it looks like maybe they are phasing out that support, which would be disasterous for this AS, both in webhook and bot mode.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The username & avatar changes definitely work as of now, not sure what will happen in the future.

// this was throwing an error when the bot was invited to a room by a user on
// a different homeserver ({"errcode":"M_FORBIDDEN","error":"You are not invited to this room."})
Promise.delay(30 * 1000).then(() => this.getBotIntent().join(ev.room_id));

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty line.

And this feels like a bug in Synapse :s. I wonder if it can be reproduced with a normal client or if it is related to the appservice API.

@erdnaxeli
Copy link
Contributor

The in / out webhooks still work, that's good. I test to link a room with event API tomorrow.

@erdnaxeli
Copy link
Contributor

When issuing a link command, I got this message: @erdnaxeli:cervoi.se: Cannot link - TypeError: Cannot read property 'profile' of undefined.

}).then((response) => {
if (!response.user && response.user.profile) return;

if (!this._slack_bot_id !== response.user.profile.bot_id) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error came from here, because response his:

{ ok: false,
  error: 'missing_scope',
  needed: 'users:read',
  provided: 'identify,bot,channels:history,groups:history,team:read,files:write:user' }

I added "users:read" in oauth permission, and "user_change" in events, but now when I add the link, I got the message "Row is now pending-name" but the room does not show up in rooms list and link is not working.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you providing both the bot & user tokens? --slack_bot_token xoxb-xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxx --slack_user_token xoxp-xxxxxxxx-xxxxxxxxx-xxxxxxxx-xxxxxxxx

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and did you have the files:write:user permission. I don't think you would need this, but it would help me debug if I knew how your's was set

@erdnaxeli
Copy link
Contributor

erdnaxeli commented Jan 26, 2018 via email

@ewingrj ewingrj mentioned this pull request Jan 26, 2018
@Cadair
Copy link
Collaborator

Cadair commented Feb 17, 2018

Any progress on this one? I have a slack team that's run out of integrations, and I could really do with this!

the rooms.

4. Click on `Event Subscriptions` and enable them. At this point, the bridge needs to be
started as slack will do some verification of the request rul. The request url should be

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo rul=url

@Cadair
Copy link
Collaborator

Cadair commented May 11, 2018

For what it is worth, I have been running this on a couple of slack teams for a few weeks now and everything seems to be working perfectly.

@geleeroyale
Copy link

I want to bring this PR to attention again - maybe it can be merged? Contributor perissology (Giveth) made this version and is running it for our bridge since January and it works really great.

Many other communities come to us and ask for bridging - it would be great to give them a detailed how-to with the appservice, but as of now we have to say "It's custom, changes to official service are pending review".

@ara4n
Copy link
Member

ara4n commented Sep 17, 2018

@Half-Shot when you rejoin us next week please can you put this at the top of your todo list?

@Half-Shot
Copy link
Contributor

Sure.

@Cadair
Copy link
Collaborator

Cadair commented Sep 18, 2018

Once this is in I can update my branches and send a couple more PRs with support for gitter-as style edits etc.

@Half-Shot
Copy link
Contributor

Ooh, yes that would be exciting @Cadair

@Half-Shot Half-Shot self-assigned this Sep 24, 2018
@Half-Shot
Copy link
Contributor

Thanks @perissology for the hard work in doing this! I've continued the PR on #89.

@Half-Shot Half-Shot closed this Sep 24, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants