Jelajahi Sumber

Add slack notification hook

Sotaro KARASAWA 10 tahun lalu
induk
melakukan
fc720abedc
5 mengubah file dengan 106 tambahan dan 56 penghapusan
  1. 20 7
      lib/models/page.js
  2. 0 47
      lib/routes/admin.js
  3. 18 0
      lib/routes/page.js
  4. 67 2
      lib/util/slack.js
  5. 1 0
      resource/js/crowi.js

+ 20 - 7
lib/models/page.js

@@ -59,6 +59,15 @@ module.exports = function(crowi) {
     return false;
     return false;
   };
   };
 
 
+  pageSchema.methods.getSlackChannel = function() {
+    //var extended = this.extended;
+    //debug('getSlackChannel.extended', extended);
+
+    //var slack = extended.slack || '';
+
+    //return slack;
+  };
+
   pageSchema.methods.isPortal = function() {
   pageSchema.methods.isPortal = function() {
     return isPortalPath(this.path);
     return isPortalPath(this.path);
   };
   };
@@ -299,13 +308,13 @@ module.exports = function(crowi) {
     var forbiddenPages = [
     var forbiddenPages = [
       /\^|\$|\*|\+|\#/,
       /\^|\$|\*|\+|\#/,
       /^\/_api\/.*/,
       /^\/_api\/.*/,
-/^\/\-\/.*/,
-/^\/_r\/.*/,
-/^\/user\/[^\/]+\/(bookmarks|comments|activities|pages|recent-create|recent-edit)/, // reserved
-/^http:\/\/.+$/, // avoid miss in renaming
-/.+\/edit$/,
-/.+\.md$/,
-/^\/(installer|register|login|logout|admin|me|files|trash|paste|comments).+/,
+      /^\/\-\/.*/,
+      /^\/_r\/.*/,
+      /^\/user\/[^\/]+\/(bookmarks|comments|activities|pages|recent-create|recent-edit)/, // reserved
+      /^http:\/\/.+$/, // avoid miss in renaming
+      /.+\/edit$/,
+      /.+\.md$/,
+      /^\/(installer|register|login|logout|admin|me|files|trash|paste|comments).+/,
     ];
     ];
 
 
     var isCreatable = true;
     var isCreatable = true;
@@ -541,6 +550,10 @@ module.exports = function(crowi) {
     });
     });
   };
   };
 
 
+  pageSchema.statics.updateExtended = function(page, extended) {
+    return this.updatePage(page, extended);
+  };
+
   pageSchema.statics.updateGrant = function(page, grant, userData) {
   pageSchema.statics.updateGrant = function(page, grant, userData) {
     var self = this;
     var self = this;
 
 

+ 0 - 47
lib/routes/admin.js

@@ -281,53 +281,6 @@ module.exports = function(crowi, app) {
     });
     });
   };
   };
 
 
-  actions.slackauth = function(req, res) {
-    //debug(req.query.code);
-    //var Botkit = require('botkit');
-    //var controller = Botkit.slackbot({debug: true});
-    //var config = crowi.getConfig();
-
-    //controller.configureSlackApp({
-    //  clientId: '2462768682.25922619424',
-    //  clientSecret: '2bbbc1c5d355e128ffd009a5d57629b9',
-    //  redirectUri: config.crowi['app:url'] + '/slackauth',
-    //  scopes: ['chat:write:bot']
-    //});
-
-    //var bot = controller.spawn();
-    //bot.api.oauth.access({code: req.query.code}, function (err, response) {
-    //  debug(err, response);
-    //});
-    //var accessToken = 'xoxp-2462768682-2462768686-25940861495-3e4cc9168a';
-    //var accessToken = 'xoxp-2462768682-2462768686-26103706022-46943fb5ec';
-    //
-    // access_token: '',
-    // scope: 'identify,chat:write:bot',
-    // team_name: '',
-    // team_id: '' }
-    //var bot = controller.spawn({token: accessToken});
-    //bot.api.chat.postMessage({
-    //  channel: '#xtest2',
-    //  username: 'Crowi',
-    //  text: '/hoge/fuga/piyo is updated.',
-    //  attachments: [
-    //    {
-    //      color: '#263a3c',
-    //      author_name: '@sotarok',
-    //      author_link: 'http://localhost:3000/user/sotarok',
-    //      author_icon: 'https://crowi-strk-dev.s3.amazonaws.com/user/56c9dbf860ab5bc62647d84a.png',
-    //      title: "/hoge/fuga/piyo",
-    //      title_link: "http://localhost:3000/hoge/fuga/piyo",
-    //      text: '*# sotarok*\n\nshellに続き、初心者が頑張って理解していくノート的記事です。\nGitHubが常識と化してきた今日この頃、チャレンジしてみたものの、そもそもGitってなんなのかわからないと使いこなせない、っていうか挫折すると思います。私はしました。\nなので、起き上がってまずGitについて本当に一から理解を試みました。\n\n***\n  \n*## Gitって何?*\n\nGitとは、**[バージョン管理システム](https://ja.wikipedia.org/wiki/%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E7%AE%A1%E7%90%86%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0)**のひとつです。\n        バージョン管理‥? :open_mouth: \nバージョンすなわち変更履歴の管理です。\n\n例えばなにかファイルの書き換えをするとき、元データを失わないためにどのような工夫をするでしょうか。ほとんどの場合、保存用にコピーを作成しておくというのが定番の方法だと思います。\nですが、誰しもこんな経験があるのでは。\n\n - 元データの保管が面倒\n  - \'meeting_3月.txt\'、\'meeting_最新.txt\'といった名前のデータが複数できてしまう\n   - チームで触っていて、最後に書き換えたのが誰なのかわからない\n    - 先輩も同時に編集していたのに、知らずにタッチの差で上書きしてしまった\n     - 書き換えたよ~と言われても(あるいは自分でも)、どこを換えたかわからない\n      - 何回か前の更新状態の方が良かった、戻したい…\n      \n      ある~~~!!\n      こんな事態を解消してくれるのが**Gitというバージョン管理システム**です。',
-    //      mrkdwn_in: ["text"],
-    //    },
-    //  ],
-    //});
-
-    //var code = req.query.);
-    res.render('admin/slackauth', {});
-  };
-
   actions.api = {};
   actions.api = {};
   actions.api.appSetting = function(req, res) {
   actions.api.appSetting = function(req, res) {
     var form = req.form.settingForm;
     var form = req.form.settingForm;

+ 18 - 0
lib/routes/page.js

@@ -226,6 +226,7 @@ module.exports = function(crowi, app) {
 
 
     var redirectPath = encodeURI(path);
     var redirectPath = encodeURI(path);
     var pageData = {};
     var pageData = {};
+    var updateOrCreate;
 
 
     // set to render
     // set to render
     res.locals.pageForm = pageForm;
     res.locals.pageForm = pageForm;
@@ -254,16 +255,33 @@ module.exports = function(crowi, app) {
       if (data) {
       if (data) {
         // update existing page
         // update existing page
         var newRevision = Revision.prepareRevision(data, body, req.user);
         var newRevision = Revision.prepareRevision(data, body, req.user);
+        updateOrCreate = 'update';
         return Page.pushRevision(data, newRevision, req.user);
         return Page.pushRevision(data, newRevision, req.user);
       } else {
       } else {
         // new page
         // new page
+        updateOrCreate = 'create';
         return Page.create(path, body, req.user, {grant: grant});
         return Page.create(path, body, req.user, {grant: grant});
       }
       }
     }).then(function(data) {
     }).then(function(data) {
+      // data is a saved page data.
+      pageData = data;
       if (!data) {
       if (!data) {
         throw new Error('Data not found');
         throw new Error('Data not found');
       }
       }
+      // TODO: move to events
       crowi.getIo().sockets.emit('page edited', {page: data, user: req.user});
       crowi.getIo().sockets.emit('page edited', {page: data, user: req.user});
+      if (notify.slack) {
+        //if (notify.slack.channel && pageData.getSlackChannel()) {
+        //  // through
+        //  Page.updateNotify(data).then(function(){}).catch(function(){});
+        //}
+        if (notify.slack.on && notify.slack.channel) {
+          if (crowi.slack) {
+            var message = crowi.slack.prepareSlackMessage(pageData, req.user, notify.slack.channel, updateOrCreate);
+            crowi.slack.post(message).then(function(){}).catch(function(){});
+          }
+        }
+      }
 
 
       if (grant != data.grant) {
       if (grant != data.grant) {
         return Page.updateGrant(data, grant, req.user).then(function(data) {
         return Page.updateGrant(data, grant, req.user).then(function(data) {

+ 67 - 2
lib/util/slack.js

@@ -8,11 +8,17 @@ module.exports = function(crowi) {
   var debug = require('debug')('crowi:util:slack'),
   var debug = require('debug')('crowi:util:slack'),
     Config = crowi.model('Config'),
     Config = crowi.model('Config'),
     Botkit = require('botkit'),
     Botkit = require('botkit'),
+    sprintf = require('sprintf'),
+    bot = null,
     slack = {};
     slack = {};
   slack.controller = undefined;
   slack.controller = undefined;
 
 
   slack.createBot = function() {
   slack.createBot = function() {
-    var bot;
+    // alreay created
+    if (bot) {
+      return bot;
+    }
+
     var config = crowi.getConfig();
     var config = crowi.getConfig();
 
 
     if (!slack.controller) {
     if (!slack.controller) {
@@ -28,7 +34,6 @@ module.exports = function(crowi) {
     } else {
     } else {
       bot = slack.controller.spawn();
       bot = slack.controller.spawn();
     }
     }
-
     return bot;
     return bot;
   };
   };
 
 
@@ -71,5 +76,65 @@ module.exports = function(crowi) {
     return slack.controller.getAuthorizeURL();
     return slack.controller.getAuthorizeURL();
   }
   }
 
 
+  slack.post = function (message) {
+    var bot = slack.createBot();
+
+    return new Promise(function(resolve, reject) {
+      bot.api.chat.postMessage(message, function(err, res) {
+        if (err) {
+          debug('Post error', err, res);
+          debug('Sent data to slack is:', message);
+          return reject(err);
+        }
+
+        resolve(res);
+      });
+    });
+  };
+
+  slack.prepareSlackMessage = function(page, user, channel, updateType) {
+    var config = crowi.getConfig();
+    var url = config.crowi['app:url'] || '';
+
+    var body = page.revision.body;
+    if (body.length > 2000) {
+      body = body.substr(0, 2000) + '...';
+    }
+
+    var attachment = {
+      color: '#263a3c',
+      author_name: '@' + user.username,
+      author_link: url + '/user/' + user.username,
+      author_icon: user.image,
+      title: page.path,
+      title_link: url + page.path,
+      text: body,
+      mrkdwn_in: ["text"],
+    };
+    if (user.image) {
+      attachment.author_icon = user.image;
+    }
+
+    var message = {
+      channel: '#' + channel,
+      username: 'Crowi',
+      text: this.getSlackMessageText(page.path, user, updateType),
+      attachments: [attachment],
+    };
+
+    return message;
+  };
+
+  slack.getSlackMessageText = function(path, user, updateType) {
+    var text;
+
+    if (updateType == 'create') {
+      text = sprintf('%s created a new page! %s', user.username, path);
+    } else {
+      text = sprintf('%s updated %s', user.username, path);
+    }
+
+    return text;
+  };
   return slack;
   return slack;
 };
 };

+ 1 - 0
resource/js/crowi.js

@@ -224,6 +224,7 @@ $(function() {
   var revisionCreatedAt = $('#content-main').data('page-revision-created');
   var revisionCreatedAt = $('#content-main').data('page-revision-created');
   var currentUser = $('#content-main').data('current-user');
   var currentUser = $('#content-main').data('current-user');
   var isSeen = $('#content-main').data('page-is-seen');
   var isSeen = $('#content-main').data('page-is-seen');
+  var pagePath= $('#content-main').data('page-path');
 
 
   Crowi.linkPath();
   Crowi.linkPath();