明日にはでっかい太陽が昇るかもしれません。

「覚悟」とは!! 暗闇の荒野に!!進むべき道を切り開く事だッ!

Chat Ops はじめました?

github.com

昨年末から、担当するプロジェクトが変わり、新たにチームを編成することになったので、今度の開発環境では、ぜひともメールをチャットに置き換えたいと思い、 Let's Chat を社内の開発サーバに導入してみています。

別に Chat Ops にするつもりはなかったですが、 Trac から通知するプラグインを作成しているので、全面的に導入を狙ってみます。

導入手手順はおいおいまとめるとして、先行導入で分かった問題として、 Let's Chat はデスクトップ通知が ON/OFF しか選べないため、人によっては、 ON にした場合に通知で気が散るというものがあります。

リアルタイムにフォローをするため、私はすべてのやり取りの通知がほしいですが、メンバによっては、メンションありの場合だけ通知できるようになると便利です。

というわけで、 0.4.5 をベースにデスクトップ通知をメンションありの場合だけできるように設定を拡張してみました。

diff --git a/app/core/account.js b/app/core/account.js
index 539eb4e..baa100e 100644
--- a/app/core/account.js
+++ b/app/core/account.js
@@ -39,6 +39,9 @@ AccountManager.prototype.update = function(id, options, cb) {
         if (options.email) {
             user.email = options.email;
         }
+        if (options.hasOwnProperty('notificationsMentionedOnly')) {
+            user.notificationsMentionedOnly = options.notificationsMentionedOnly;
+        }
 
         if (options.username && options.username !== user.username) {
             var xmppConns = this.core.presence.system.connections.query({
diff --git a/app/models/user.js b/app/models/user.js
index 6eceda5..2d3b335 100644
--- a/app/models/user.js
+++ b/app/models/user.js
@@ -86,6 +86,10 @@ var UserSchema = new mongoose.Schema({
         type: String,
         trim: true
     },
+    notificationsMentionedOnly: {
+        type: Boolean,
+        default: false
+    },
     rooms: [{
        type: ObjectId,
        ref: 'Room'
@@ -271,7 +275,8 @@ UserSchema.method('toJSON', function() {
         lastName: this.lastName,
         username: this.username,
         displayName: this.displayName,
-        avatar: this.avatar
+        avatar: this.avatar,
+        notificationsMentionedOnly: this.notificationsMentionedOnly
     };
 });
 
diff --git a/media/js/views/modals.js b/media/js/views/modals.js
index 6ac2c12..48c02df 100644
--- a/media/js/views/modals.js
+++ b/media/js/views/modals.js
@@ -167,7 +167,8 @@
 
     window.LCB.NotificationsModalView = Backbone.View.extend({
         events: {
-            'click [name=desktop-notifications]': 'toggleDesktopNotifications'
+            'click [name=desktop-notifications]': 'toggleDesktopNotifications',
+            'click [name=notifications-mentionedonly]': 'toggleNotificationsMentionedOnly'
         },
         initialize: function() {
             this.render();
@@ -178,17 +179,31 @@
               .siblings().hide();
             if (!notify.isSupported) {
                 $input.attr('disabled', true);
-                // Welp we're done here
-                return;
             }
-            if (notify.permissionLevel() === notify.PERMISSION_GRANTED) {
+            else if (notify.permissionLevel() === notify.PERMISSION_GRANTED) {
                 $input.find('.enabled').show()
                   .siblings().hide();
             }
-            if (notify.permissionLevel() === notify.PERMISSION_DENIED) {
+            else if (notify.permissionLevel() === notify.PERMISSION_DENIED) {
                 $input.find('.blocked').show()
                   .siblings().hide();
             }
+
+            var $input = this.$('[name=notifications-mentionedonly]');
+            $input.find('.disabled').show()
+              .siblings().hide();
+            $.get('./notifications', function(data) {
+                if (data.status == 'error') {
+                    $input.find('.disabled').show()
+                      .siblings().hide();
+                    return;
+                }
+
+                if (data.mentionedOnly) {
+                    $input.find('.enabled').show()
+                      .siblings().hide();
+                }
+            });
         },
         toggleDesktopNotifications: function() {
             var that = this;
@@ -198,6 +213,18 @@
             notify.requestPermission(function() {
                 that.render();
             });
+        },
+        toggleNotificationsMentionedOnly: function() {
+            var that = this;
+            if (!notify.isSupported) {
+                return;
+            }
+            $.post('./notifications/mentionedOnly', function(data) {
+                if (data.status == 'error') {
+                    return;
+                }
+                that.render();
+            });
         }
     });
 
diff --git a/media/js/views/window.js b/media/js/views/window.js
index f7cda80..1809f40 100644
--- a/media/js/views/window.js
+++ b/media/js/views/window.js
@@ -168,10 +168,15 @@
             notify.config({
                 pageVisibility: false
             });
+            var that = this;
             this.client = options.client;
             this.rooms = options.rooms;
             $(window).on('focus blur unload', _.bind(this.onFocusBlur, this));
             this.rooms.on('messages:new', this.onNewMessage, this);
+
+            $.get('./notifications', function(data) {
+                that.notificationsMentionedOnly = data.mentionedOnly;
+            });
         },
         onFocusBlur: function(e) {
             this.focus = (e.type === 'focus');
@@ -193,6 +198,10 @@
                 notify.permissionLevel() != notify.PERMISSION_GRANTED) {
                 return;
             }
+            if ( !message.mentioned &&
+                this.notificationsMentionedOnly) {
+                return;
+            }
 
             var roomID = message.room.id,
                 avatar = message.owner.avatar,
diff --git a/templates/includes/modals/notifications.html b/templates/includes/modals/notifications.html
index d9e5d81..d992943 100644
--- a/templates/includes/modals/notifications.html
+++ b/templates/includes/modals/notifications.html
@@ -20,6 +20,17 @@
                             <br /><small><$ __('Please check your browser settings') $></small>
                         </span>
                     </button>
+                    <button name="notifications-mentionedonly" class="btn btn-info" style="display: block; margin-top: 10px;">
+                        <span class="enabled">
+                            Notify mentioned messages only
+                        </span>
+                        <span class="disabled">
+                            Notify any messages
+                        </span>
+                        <span class="blocked">
+                            Select notifications are <strong>blocked</strong>
+                        </span>
+                    </button>
                 </div>
             </div>
          </div>

全体の設定は以下のようにしました。

--- a/settings.yml
+++ b/settings.yml
 rooms:
   private: true
 
+ notifications:
+   mentionedOnly: true

この修正で、とりあえずユーザ毎にメンションなしのメッセージを通知するか否かを設定できるようになりました。

あと、ついでに履歴検索で正規表現を使えるように修正しました。( 人生楽しまなきゃもったいない!: Let's Chatを入れてみた からもろパクリですが)

diff --git a/app/core/messages.js b/app/core/messages.js
index 24bb51f..5471257 100644
--- a/app/core/messages.js
+++ b/app/core/messages.js
@@ -90,7 +90,8 @@ MessageManager.prototype.list = function(options, cb) {
     }
 
     if (options.query) {
-        find = find.find({$text: {$search: options.query}});
+        var r = new RegExp(options.query, "i")
+        find = find.find({"text": {$regex:r}});
     }
 
     if (options.expand) {

デスクトップ通知については、本家の Slack が充実しているらしいので、修正を続けて、機能が充実したら master への PR も出してみたいな。