# Common event system for chatrooms - a specification

**URL:** https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245
**Category:** Feature
**Created:** [16.Март.2017 13:01:04 UTC](https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245 "2017-03-16T13:01:04Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [16.Март.2017 13:01:05 UTC](https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245/1 "2017-03-16T13:01:05Z")

</div>

One of the GSOC ideas on GitHub is creating a “[Common Event System for Chatrooms](https://github.com/discourse/discourse/wiki/Summer-of-Code-2017-Ideas-List#common-event-system-for-chatrooms)”

> [@](#):
>
> Ideally we’d have a set of plugins for various chatrooms, like discourse-hipchat, discourse-slack, etc, that would all expose the same event system.
> 
> Then we could do code like DiscourseEvent.trigger(:notify\_chat, “some chatroom text”) and have it work regardless of your chat software.

I like the sound of this idea, so this is an attempt at a more comprehensive description of how it could be implemented. Hopefully this will give a starting point for some discussion about what people would like to get out of a feature like this.

* * *
Edit 17/03/2017: I've added and ~~removed~~ some stuff based on comments below.
* * *

# What we already have

[https://meta.discourse.org/t/the-official-discourse-slack-plugin/51412](https://meta.discourse.org/t/the-official-discourse-slack-plugin/51412)

The Discourse-Slack plugin is a great way of getting real-time notifications of Discourse posts. It can post to ‘group chats’ in Slack, or post to individuals. Notifications can be setup for specific categories (tags [coming soon](https://github.com/discourse/discourse-slack-official/pull/15)), either for “new topics”, or “all replies”.

# Common event system

### The idea

Creating plugins which provide similar functionality to the slack plugin, but for other communication platforms, is totally possible right now. However, this will result in a massive amount of code duplication, as a lot of the logic will be the same between different chat systems. Therefore a ‘shared’ chat system (as a plugin), would be an efficient & maintainable way to expand to multiple platforms.

### Scope

As an initial implementation, I wouldn’t expect functionality to go much further than the current functionality of the Slack plugin, however there is scope to add more functionality such as actually making posts on Discourse from your chosen messaging platform, but that’s material for a future discussion.

### Structure

The “Common event system” would take care of managing “subscriptions” (which categories/tags to subscribe to for a given “chat”). At its simplest level, it would maintain a table with rows like this. Yes, it would need to be more complicated than 3 text fields, but hopefully this illustrates the functionality.

```plaintext
| CHAT_SYSTEM | CHAT_ID | SUBSCRIPTIONS |
|-------------|-----------------|---------------------------------|
| telegram | @davidtaylorhq | c/meta,c/plugins,t/pr-welcome |
| facebook | group_75462363 | c/lounge |
| slack | #general | c/support, c/bugs |

```

Each of the chat\_systems would be an independent plugin, which deals with the platform-specific stuff. These plugins would receive information from the “common event system” using similar systems as the current event hooks. So you’d end up with something like:

```ruby
DiscourseEvent.on(:notify_chat, :telegram) do |information|
    # Send a message to the specified telegram chat using the information provided
end

```

### Permissions

Initially this would be admin-only, so no permission checks would be necessary

### Authenticating

Initially this would be admin-only, so no authentication would be necessary

### User Interface

The “common event system” should have its own pane in the admin interface, listing all current subscriptions (effectively each of the rows in the pseudo-table above). I imagine the UI to be very similar to the current slack plugin:

[![](https://global.discourse-cdn.com/meta/optimized/3X/0/9/090d7887804ce156c022163d9fc9cdfe3be6511a_1_690x238.png) ](https://global.discourse-cdn.com/meta/optimized/3X/0/9/090d7887804ce156c022163d9fc9cdfe3be6511a_1_690x238.png)

Providers could also implement something like “slash commands” for changing subscription settings, like the slack plugin does right now:

```plaintext
/discourse [watch|follow|mute|help|status] [category|all]

```

## Possible providers

Each of these could be implemented in separate plugins, keeping things modular & maintainable:

**Slack** - the slack plugin already exists, making use of the [api](https://api.slack.com/web)  
**Telegram** - Mature REST [bot API](https://core.telegram.org/bots/api), which I have used in the past.  
**Facebook Messenger** - [Bot API](https://developers.facebook.com/docs/messenger-platform) available  
**Gitter** - Can add things to ‘activity stream’ using the [services library](https://github.com/gitterHQ/services). @jafeth.diazc has more info [here](https://meta.discourse.org/t/gitter-post-notifications-to-chat-post-transcripts-to-forum/51247/2)  
**HipChat** [(thread)](https://meta.discourse.org/t/hipchat-post-notifications-to-chat-post-transcripts-to-forum/51248/1) - [API available](https://www.hipchat.com/docs/apiv2), see [discourse-akismet-hipchat](https://github.com/discourse/discourse-akismet-hipchat)  
**Mattermost** [(thread)](https://meta.discourse.org/t/mattermost-post-notifications-to-chat-post-transcripts-to-forum/51246) - [API available](https://docs.mattermost.com/developer/api.html)

**[others]** - Hopefully having a central system for managing the complicated user/permissions logic would enable plugin developers to easily create plugins for any service with an API.

* * *
I'd love to hear people's thoughts on this spec, if there's anything that's not clear please let me know and I'll do my best to improve the description.

---

<div class="post-metadata">

### Author: ![mcwumbly](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mcwumbly/32/103861_2.png) [@mcwumbly](https://meta.discourse.org/u/mcwumbly)
#### Post date: [16.Март.2017 14:07:02 UTC](https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245/2 "2017-03-16T14:07:02Z")

</div>

I think subscriptions should have a type.

In the UI, rather than a column just for Category, there would be a column for Type with a dropdown to select Category or Tag. In the future, I think you could also choose Topic or User, for instance.

Depending on the type, the next column over would allow you to choose the elements of that type that you want to subscribe to. If you select Category for Type, then you can choose _which_ categories. If you choose Tag for the type, then you can select _which_ tags.

This avoids [ambiguity about whether these choices are unions or intersections](https://github.com/discourse/discourse-slack-official/pull/15#discussion_r105857846) and allows for the feature to grow more naturally to meet future needs.

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [16.Март.2017 14:45:07 UTC](https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245/4 "2017-03-16T14:45:07Z")

</div>

I have huge mixed feelings here, it feels like starting at step 100 instead of step 0

Why does core need to worry about this stuff?

Isn’t a simpler way of going about this simply renaming “slack plugin” to “chat integration plugin” and adding extra providers for other chat platforms?

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [16.Март.2017 14:53:08 UTC](https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245/5 "2017-03-16T14:53:08Z")

</div>

Also I’m not sure about making this available to every user vs only admins.

And about permissions you should choose one user for each subscription so it’s very clear what he can read. You can create multiple bot accounts and anchor every subscription in only one account.

---

<div class="post-metadata">

### Author: ![eviltrout](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/eviltrout/32/5275_2.png) [@eviltrout](https://meta.discourse.org/u/eviltrout)
#### Post date: [16.Март.2017 15:21:32 UTC](https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245/6 "2017-03-16T15:21:32Z")

</div>

Thanks for the effort @david but I agree with @sam it’s above and beyond what I had in mind. When in doubt I like to keep things simple and build up 🙂

1. This should definitely be a plugin, as not every discourse wants to integrate with a chat system. Something like `discourse-chat` for core support, and then `discourse-chat-slack`, `discourse-chat-hipchat` for adapters.

2. I also agree with @falco that it should begin with only supporting admins. I don’t have a problem with an admin entering an API on an admin page to configure it either – fancy configuration by visiting a page would obviously be better but let’s start simple 🙂

3. The core plugin would attach to existing events in the site and expose others, like: `DiscourseEvent.trigger(:notify_chat, msg)` where `msg` would be an object full of things we can expose to chat providers.

4. Providers would then listen for that and do the work necessary to publish.

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [16.Март.2017 21:05:50 UTC](https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245/7 "2017-03-16T21:05:50Z")

</div>

> [@sam](#):
>
> Зачем ядру нужно беспокоиться об этом?

> [@eviltrout](#):
>
> Что-то вроде discourse-chat для поддержки в ядре, а затем discourse-chat-slack, discourse-chat-hipchat для адаптеров.

Да, думаю, это материал для плагина, и такая система названий звучит идеально.

> [@sam](#):
>
> Разве более простой способ не заключается в том, чтобы просто переименовать “slack plugin” в “chat integration plugin” и добавить дополнительные провайдеры для других чат-платформ?

По сути, я имею в виду именно это, но вместо того, чтобы добавлять всё в один плагин, я думаю, что более модульный подход был бы лучше. Стартовой точкой для любой работы, безусловно, станет текущий плагин slack.

> [@Falco](#):
>
> Также я не уверен насчёт того, делать ли это доступным для всех пользователей или только для администраторов.

Думаю, это полностью зависит от направления, в котором вы хотите развивать интеграции с чатами. Это инструмент для тех, кто управляет форумом, для администрирования и модерации, или это способ для участников быть в курсе происходящего?

Возьмём в пример meta-форум: если команда `@team` хотела бы получать уведомления о новых постах в канале #Contribute > Bug в своём Slack-чате, они могли бы сделать это легко и просто. Однако, если бы я (как обычный пользователь) хотел получать уведомления в Telegram о новых плагинах, у меня не было бы такой возможности.

Конечно, начинать с того, что это доступно только администраторам, — разумный план, но я действительно думаю, что эта функция была бы полезна многим пользователям — её определённо использовали бы в сообществе, которым я управляю.

> [@eviltrout](#):
>
> Ядровый плагин будет подключаться к существующим событиям на сайте и предоставлять другие, например: DiscourseEvent.trigger(:notify\_chat, msg), где msg будет объектом, содержащим всё, что мы можем предоставить провайдерам чата.

Я не до конца понимаю это. Если вы не предполагаете какую-либо модель “подписки” в общей системе событий, то зачем нужно отдельное событие “notify chat”, когда плагины для чата могут вполне легко подключиться к событию `:post_created`?

* * *
[quote="eviltrout, post:6, topic:59245"] это выходит за рамки того, что я имел в виду. В случае сомнений я предпочитаю держать всё простым и наращивать функциональность постепенно. [/quote] Я понимаю это, начинать с простого определённо лучше. Я как бы рассматривал плагин discourse-slack как отправную точку, возможно, поэтому я зашёл слишком далеко.

В конечном счёте, всё сводится к тому, для кого эта функция и каков её сценарий использования? Я думал об этом как об ещё одном способе для пользователей получать обновления, тогда как вы, кажется, думаете об этом как об инструменте для администраторов/модераторов?

---

<div class="post-metadata">

### Author: ![eviltrout](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/eviltrout/32/5275_2.png) [@eviltrout](https://meta.discourse.org/u/eviltrout)
#### Post date: [17.Март.2017 14:34:30 UTC](https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245/8 "2017-03-17T14:34:30Z")

</div>

> [@david](#):
>
> I don’t fully understand this. If you’re not envisioning any kind of “subscription” model in the common event system, then why is there a need for a separate “notify chat” event, when chat plugins can quite easily attach to a :post\_created event?

I assume that if today you started work on a second chat adapter, you’d end up copying and pasting a bunch of code from the slack one. That’s the stuff that should live in the core plugin! In particular, the admin page the filter rules. The core plugin would watch `post_created`, check those filters, then trigger `notify_chat` for delivery. Any adapters that receive `notify_chat` would just send it, and not worry about filters themselves.

> [@david](#):
>
> Ultimately what I think it all comes down to is who is this feature for, and what’s its use case? I’ve been thinking of it as another way for users to receive updates, whereas I think you’re thinking about it as an admin/mod tool?

Not exactly – an admin has to set it up, but it can be used by public chatrooms. For example, if you are in the emberjs slack, you might want to see when new posts are made on the emberjs discussion board. That has to be set up by an admin, but consumed by regular users.

Once the core product is built we can look into layering user level messages on top, but like we said earlier, that’s a whole bunch of work that depends on other stuff working nicely first.

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [17.Март.2017 21:41:56 UTC](https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245/9 "2017-03-17T21:41:56Z")

</div>

Thanks for the feedback. I’ve trimmed down my “spec” in the first post, so that it’s a more realistic starting point: admin only, with no fancy permission checks or authentication.

Is that more in line with what you’re thinking of?

---

<div class="post-metadata">

### Author: ![eviltrout](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/eviltrout/32/5275_2.png) [@eviltrout](https://meta.discourse.org/u/eviltrout)
#### Post date: [18.Март.2017 18:40:27 UTC](https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245/10 "2017-03-18T18:40:27Z")

</div>

Looks a lot better to me thanks! From there we can build on many more features.

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [18.Март.2017 23:59:57 UTC](https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245/11 "2017-03-18T23:59:57Z")

</div>

Keep in mind, discourse plugins can source gems, so all the central logic can live in a shared gem

It would also be a fairly interesting excersize sorting out workflows, testing and so on

---

<div class="post-metadata">

### Author: ![ara4n](https://avatars.discourse-cdn.com/v4/letter/a/a8b319/32.png) [@ara4n](https://meta.discourse.org/u/ara4n)
#### Post date: [25.Март.2017 18:46:56 UTC](https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245/12 "2017-03-25T18:46:56Z")

</div>

There seems to be huge overlap between this idea and [Matrix.org](http://Matrix.org) (also a GSoC org), which provides an existing open standard for interoperable events between chat systems, and much else, including bridges to slack, irc, discord, telegram, etc. Perhaps an alternative angle might be to write a discourse\<-\>matrix bridge?

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [25.Март.2017 21:03:54 UTC](https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245/13 "2017-03-25T21:03:54Z")

</div>

[Matrix.org](http://Matrix.org) certainly looks like a cool project, but I think I’d view it as just another chat provider that could be hooked into the ‘common event system’. I only had a brief read of their website, so please correct me if I’ve got any of this wrong.

While Matrix does aim to bridge loads of different services, it looks to me like most of those are still in very early development ([this list](https://matrix.org/docs/projects/try-matrix-now.html#application-services) shows most integrations in alpha or early beta). The protocol is currently text-only, and requires a client connecting to some kind of ‘home server’.

Using Matrix as a way to get messages to Slack/Telegram/Gitter etc. will introduce another point of failure - in my opinion, using the native APIs for these services will provide a better user experience, especially when it comes to things like ‘prettifying’ the messages.

---

<div class="post-metadata">

### Author: ![ara4n](https://avatars.discourse-cdn.com/v4/letter/a/a8b319/32.png) [@ara4n](https://meta.discourse.org/u/ara4n)
#### Post date: [31.Март.2017 17:58:44 UTC](https://meta.discourse.org/t/common-event-system-for-chatrooms-a-specification/59245/14 "2017-03-31T17:58:44Z")

</div>

Yup, there are a few misconceptions here (probably because the [matrix.org](http://matrix.org) website is overdue an update, which should be going live next week):

- Matrix doesn’t aim to be yet another chat provider, but instead decentralised glue between existing chat providers. It’s aiming to fulfil precisely the use case that you’re talking about here.
- Yes, many bridges are alpha, but the ones in beta are generally very usable - we’re just very conservative about declaring stuff production-grade. Particularly the IRC/Slack/Gitter ones are robust; i believe around 5% of the connections to Freenode for instance are currently from Matrix.
- The protocol is not remotely text only; the point is that it supports freeform JSON data - folks sync anything from IMs, HTML, Markdown, WebRTC setup, MIDI, IOT data, VR world data etc over it.
- Yes, the architecture is that you’d go discourse\<-\>Matrix homeserver\<-\>rest-of-matrix (both servers & clients). In future you could implement add matrix server functionality into your server itself - e.g. [GitHub - matrix-org/gomatrixserverlib: Go library for matrix federation. · GitHub](https://github.com/matrix-org/gomatrixserverlib) is a golang matrix server library we’re currently working on. However, in the short term we’ve never had any problems with folks having to run a separate matrix server, especially during dev.
- Yes, technically the Matrix indirection would introduce another point of failure. However, I think you’re wrong in saying that somehow using the native APIs will provide a better user experience - all you’re doing here is shifting the impedance mismatch to be discourse\<-\>remote\_network rather than matrix\<-\>remote\_network. Given Matrix is deliberately built to be a superset of the full expressiveness of the remote network and avoid impedance mismatches, I might argue that you would be using the right tool for the job rather than reinventing the wheel…

Meanwhile, Matrix would also give you minor useful things such as better-than-Signal end-to-end encryption, VoIP, conferencing, and support of the whole wider Matrix ecosystem & community (200+ developers).

Whatever, we’d like to get a discourse\<-\>matrix bridge running asap, whether it’s done as a one-of-many transport in your own common event system, or by just having discourse take the easier route and leverage matrix 🙂

edit: my FOSDEM main-track talk might give a bit more context on the current state of the Matrix ecosystem: [FOSDEM 2017 - Encrypting Matrix](https://fosdem.org/2017/schedule/event/encrypting_matrix/)
