├── LICENSE ├── README.md ├── assets └── javascripts │ └── discourse │ ├── connectors │ └── category-custom-settings │ │ └── slack-settings.hbs │ └── pre-initializers │ └── extend-category-for-slack.js.es6 ├── config ├── locales │ ├── client.en.yml │ └── server.en.yml └── settings.yml ├── images ├── discourse-slack-config.png └── discourse-slack-example-notification.png └── plugin.rb /LICENSE: -------------------------------------------------------------------------------- 1 | See the COPYING file in this repository. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Discourse Slack Plugin 2 | ====================== 3 | 4 | **ATTENTION:** Consider using the offical discourse Slack plugin instead: 5 | 6 | * https://meta.discourse.org/t/the-official-discourse-slack-plugin/51412 7 | * https://github.com/discourse/discourse-slack-official 8 | 9 | This [discourse](http://www.discourse.org/) plugin sends a notification to 10 | a Slack channel for each newly created topic. 11 | 12 | See: https://meta.discourse.org/t/slack-notification-plugin/32200/4 13 | 14 | ## Tested Discourse Versions 15 | 16 | * 1.3.x 17 | 18 | ## Installation 19 | 20 | Please read the offical discourse [plugin installation](https://meta.discourse.org/t/install-a-plugin/19157) 21 | documentation. 22 | 23 | If you use the (officially recommended) [docker setup](https://github.com/discourse/discourse/blob/master/docs/INSTALL.md) 24 | you can just have to add `git clone https://github.com/bernd/discourse-slack-plugin.git` 25 | to the list of `after_code` executions in your `/var/discourse/containers/app.yml` 26 | file. (filename might be different in your setup!) 27 | 28 | ```yaml 29 | hooks: 30 | after_code: 31 | - exec: 32 | cd: $home/plugins 33 | cmd: 34 | - mkdir -p plugins 35 | - git clone https://github.com/discourse/docker_manager.git 36 | - git clone https://github.com/bernd/discourse-slack-plugin.git 37 | ``` 38 | 39 | After adjusting the config file run `./launcher rebuild app` in `/var/discourse` 40 | to stop/rebuild/start the discourse instance. 41 | 42 | ## Configuration 43 | 44 | You need to configure an [incoming-webhook](https://api.slack.com/incoming-webhooks) 45 | for your team to use this plugin. The *"Webhook URL"* is needed for the 46 | plugin configuration. 47 | 48 | Go to Admin/Settings/Slack, enable the plugin and make sure to add the 49 | *"Webhook URL"* to the *slack url* field. 50 | 51 | Example: 52 | 53 | ![Discourse slack configuration](/images/discourse-slack-config.png) 54 | 55 | ## Slack Example Notification 56 | 57 | This is how it looks like in slack. (with a custom emoji for the discourse logo) 58 | 59 | ![Discourse slack example notification](/images/discourse-slack-example-notification.png) 60 | 61 | ## Contributions 62 | 63 | All contributions are welcome! 64 | -------------------------------------------------------------------------------- /assets/javascripts/discourse/connectors/category-custom-settings/slack-settings.hbs: -------------------------------------------------------------------------------- 1 | {{#if siteSettings.allow_category_slack_channel}} 2 |
3 |
4 | 8 |
9 |
10 | {{/if}} -------------------------------------------------------------------------------- /assets/javascripts/discourse/pre-initializers/extend-category-for-slack.js.es6: -------------------------------------------------------------------------------- 1 | import property from 'ember-addons/ember-computed-decorators'; 2 | import Category from 'discourse/models/category'; 3 | 4 | export default { 5 | name: 'extend-category-for-slack', 6 | before: 'inject-discourse-objects', 7 | initialize() { 8 | 9 | Category.reopen({ 10 | 11 | @property('custom_fields.slack_channel') 12 | slack_channel: { 13 | get(channelField) { 14 | return channelField; 15 | }, 16 | set(value) { 17 | this.set("custom_fields.slack_channel", value); 18 | return value; 19 | } 20 | } 21 | 22 | }); 23 | } 24 | }; -------------------------------------------------------------------------------- /config/locales/client.en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | admin_js: 3 | admin: 4 | site_settings: 5 | categories: 6 | slack: 'Slack' 7 | js: 8 | slack: 9 | channel: "Slack channel" -------------------------------------------------------------------------------- /config/locales/server.en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | site_settings: 3 | slack_enabled: 'Check this to enable the Slack integration.' 4 | slack_url: 'Slack URL including access token.' 5 | slack_channel: 'Slack channel to post this message to. (i.e. #general, @username). Leaving blank for no fallback is helpful if using "allow category slack channel" setting.' 6 | slack_emoji: 'Slack emoji to use.' 7 | slack_posts: 'Post all new posts to Slack (not just new topics).' 8 | slack_full_names: 'Shows user full names instead of usernames (shows username if user did not set one)' 9 | allow_category_slack_channel: 'Allows each category to specify a Slack channel to post to, falls back to parent categories or the global channel' 10 | slack_category_name_in_title: 'Display the category name in the title of the post sent to Slack (e.g., "[category name] topic title")' 11 | -------------------------------------------------------------------------------- /config/settings.yml: -------------------------------------------------------------------------------- 1 | slack: 2 | slack_enabled: 3 | client: true 4 | default: false 5 | slack_url: 6 | client: true 7 | default: '' 8 | slack_channel: 9 | client: true 10 | default: '#general' 11 | slack_emoji: 12 | client: true 13 | default: ':discourse:' 14 | slack_posts: 15 | client: true 16 | default: false 17 | slack_full_names: 18 | client: true 19 | default: true 20 | allow_category_slack_channel: 21 | client: true 22 | default: false 23 | slack_category_name_in_title: 24 | client: true 25 | default: false 26 | -------------------------------------------------------------------------------- /images/discourse-slack-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bernd/discourse-slack-plugin/94f2c4517cbd477d6f85c7da879fbed51854fa84/images/discourse-slack-config.png -------------------------------------------------------------------------------- /images/discourse-slack-example-notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bernd/discourse-slack-plugin/94f2c4517cbd477d6f85c7da879fbed51854fa84/images/discourse-slack-example-notification.png -------------------------------------------------------------------------------- /plugin.rb: -------------------------------------------------------------------------------- 1 | # name: slack 2 | # about: Post new discourse content to Slack 3 | # version: 0.2.0 4 | # authors: Bernd Ahlers 5 | # url: https://github.com/bernd/discourse-slack-plugin 6 | 7 | after_initialize do 8 | DiscourseEvent.on(:post_created) do |*params| 9 | next unless SiteSetting.slack_enabled 10 | 11 | begin 12 | post, opts, user = params 13 | topic = post.topic 14 | 15 | next if topic.try(:private_message?) 16 | next if !SiteSetting.slack_posts && !post.try(:is_first_post?) 17 | next if post.post_type == Post.types[:small_action] 18 | next if post.post_type == Post.types[:moderator_action] 19 | 20 | post_url = "#{Discourse.base_url}#{post.url}" 21 | 22 | uri = URI.parse(SiteSetting.slack_url) 23 | http = Net::HTTP.new(uri.host, uri.port) 24 | http.use_ssl = true if uri.scheme == 'https' 25 | 26 | display_name = (SiteSetting.slack_full_names && user.try(:name) && user.name.length > 0) ? user.name : user.username 27 | 28 | # Default to the global site channel 29 | channel = SiteSetting.slack_channel 30 | 31 | category = topic.category 32 | # We might have a category specific channel to post to 33 | if SiteSetting.allow_category_slack_channel 34 | 35 | # We walk up the categories to the root unless we find a 36 | # channel setting on the category 37 | while category != nil do 38 | cat_channel = category.custom_fields["slack_channel"] 39 | 40 | if cat_channel != nil 41 | channel = cat_channel 42 | break 43 | end 44 | 45 | category = category.parent_category 46 | end 47 | end 48 | 49 | next if channel.blank? 50 | 51 | show_category_name = SiteSetting.slack_category_name_in_title 52 | 53 | request = Net::HTTP::Post.new(uri.path) 54 | request.add_field('Content-Type', 'application/json') 55 | request.body = { 56 | :username => SiteSetting.title, 57 | :icon_emoji => SiteSetting.slack_emoji, 58 | :channel => channel, 59 | :attachments => [ 60 | { 61 | :fallback => "New " + (post.try(:is_first_post?) ? "topic" : "post in #{topic.title}") + " by #{display_name} - #{post_url}", 62 | :pretext => "New " + (post.try(:is_first_post?) ? "topic" : "post") + " by #{display_name}:", 63 | :title => (show_category_name ? "[" + category.name + "] " : "") + topic.title, 64 | :title_link => post_url, 65 | :text => post.excerpt(200, text_entities: true, strip_links: true) 66 | } 67 | ] 68 | }.to_json 69 | 70 | response = http.request(request) 71 | case response 72 | when Net::HTTPSuccess 73 | Rails.logger.info("Slack webhook successfully sent to #{uri.host}. (post: #{post_url})") 74 | else 75 | Rails.logger.error("#{uri.host}: #{response.code} - #{response.message}") 76 | end 77 | rescue => e 78 | Rails.logger.error("Error sending Slack hook: #{e.message}") 79 | end 80 | end 81 | end 82 | --------------------------------------------------------------------------------