@ -71,56 +71,22 @@ define([
var getPropertiesData = function ( common , cb ) {
var getPropertiesData = function ( common , cb ) {
var data = { } ;
var data = { } ;
NThen ( function ( waitFor ) {
NThen ( function ( waitFor ) {
common . getPadAttribute ( 'password' , waitFor ( function ( err , val ) {
data . password = val ;
} ) ) ;
} ) . nThen ( function ( waitFor ) {
var base = common . getMetadataMgr ( ) . getPrivateData ( ) . origin ;
var base = common . getMetadataMgr ( ) . getPrivateData ( ) . origin ;
// XXX getFileData?
common . getPadAttribute ( '' , waitFor ( function ( err , val ) {
// XXX getPadMetadata
if ( err || ! val ) {
common . getPadAttribute ( 'href' , waitFor ( function ( err , val ) {
waitFor . abort ( ) ;
if ( ! val ) { return ; }
return void cb ( err || 'EEMPTY' ) ;
data . href = base + val ;
}
} ) ) ;
Util . extend ( data , val ) ;
common . getPadAttribute ( 'roHref' , waitFor ( function ( err , val ) {
if ( data . href ) { data . href = base + data . href ; }
if ( ! val ) { return ; }
if ( data . roHref ) { data . roHref = base + data . roHref ; }
data . roHref = base + val ;
} ) ) ;
common . getPadAttribute ( 'channel' , waitFor ( function ( err , val ) {
data . channel = val ;
} ) ) ;
common . getPadAttribute ( 'rtChannel' , waitFor ( function ( err , val ) {
data . rtChannel = val ;
} ) ) ;
common . getPadAttribute ( 'lastVersion' , waitFor ( function ( err , val ) {
data . lastVersion = val ;
} ) ) ;
common . getPadAttribute ( 'atime' , waitFor ( function ( err , val ) {
data . atime = val ;
} ) ) ;
common . getPadAttribute ( 'ctime' , waitFor ( function ( err , val ) {
data . ctime = val ;
} ) ) ;
common . getPadAttribute ( 'title' , waitFor ( function ( err , val ) {
data . title = val ;
} ) ) ;
common . getPadAttribute ( 'tags' , waitFor ( function ( err , val ) {
data . tags = val ;
} ) ) ;
} ) ) ;
common . getPadMetadata ( null , waitFor ( function ( obj ) {
common . getPadMetadata ( null , waitFor ( function ( obj ) {
console . log ( obj ) ;
if ( obj && obj . error ) { return ; }
if ( obj && obj . error ) { return ; }
data . owners = obj . owners ;
data . owners = obj . owners ;
data . expire = obj . expire ;
data . expire = obj . expire ;
data . pending _owners = obj . pending _owners ;
data . pending _owners = obj . pending _owners ;
} ) ) ;
} ) ) ;
/ *
common . getPadAttribute ( 'owners' , waitFor ( function ( err , val ) {
data . owners = val ;
} ) ) ;
common . getPadAttribute ( 'expire' , waitFor ( function ( err , val ) {
data . expire = val ;
} ) ) ; * /
} ) . nThen ( function ( ) {
} ) . nThen ( function ( ) {
cb ( void 0 , data ) ;
cb ( void 0 , data ) ;
} ) ;
} ) ;
@ -132,20 +98,20 @@ define([
var user = common . getMetadataMgr ( ) . getUserData ( ) ;
var user = common . getMetadataMgr ( ) . getUserData ( ) ;
var edPublic = priv . edPublic ;
var edPublic = priv . edPublic ;
var channel = data . channel ;
var channel = data . channel ;
var owners = data . owners ;
var owners = data . owners || [ ] ;
var pending _owners = data . pending _owners ;
var pending _owners = data . pending _owners || [ ] ;
var redrawAll = function ( ) { } ;
var redrawAll = function ( ) { } ;
var div1 = h ( 'div.cp-share-friends.cp-share-column ') ;
var div1 = h ( 'div.cp-share-friends.cp-share-column .cp-ownership ') ;
var div2 = h ( 'div.cp-share-friends.cp-share-column ') ;
var div2 = h ( 'div.cp-share-friends.cp-share-column .cp-ownership ') ;
var $div1 = $ ( div1 ) ;
var $div1 = $ ( div1 ) ;
var $div2 = $ ( div2 ) ;
var $div2 = $ ( div2 ) ;
// Remove owner column
// Remove owner column
var drawRemove = function ( pending ) {
var drawRemove = function ( pending ) {
var _owners = { } ;
var _owners = { } ;
var o = pending ? pending _owners : owners ;
var o = ( pending ? pending _owners : owners ) || [ ] ;
o . forEach ( function ( ed ) {
o . forEach ( function ( ed ) {
var f ;
var f ;
Object . keys ( friends ) . some ( function ( c ) {
Object . keys ( friends ) . some ( function ( c ) {
@ -154,20 +120,25 @@ define([
return true ;
return true ;
}
}
} ) ;
} ) ;
if ( ed === edPublic ) {
f = f || user ;
if ( f . name ) {
f . displayName = f . name ;
}
}
_owners [ ed ] = f || {
_owners [ ed ] = f || {
displayName : 'Unknown user: ' + ed , // XXX
displayName : Messages . _getKey ( 'owner_unknownUser' , [ ed ] ) ,
notifications : true ,
notifications : true ,
edPublic : ed ,
edPublic : ed ,
} ;
} ;
} ) ;
} ) ;
var msg = pending ? 'Remove a pending owner:'
var msg = pending ? Messages . owner _removePendingText
: 'Remove an existing owner:' ; // XXX
: Messages . owner _removeText ;
var removeCol = UIElements . getFriendsList ( msg , {
var removeCol = UIElements . getFriendsList ( msg , {
common : common ,
common : common ,
friends : _owners ,
friends : _owners ,
noFilter : true
noFilter : true
} , function ( ) {
} , function ( ) {
console . log ( arguments ) ;
} ) ;
} ) ;
var $div = $ ( removeCol . div ) ;
var $div = $ ( removeCol . div ) ;
var others1 = removeCol . others ;
var others1 = removeCol . others ;
@ -184,12 +155,13 @@ define([
} ) ;
} ) ;
// When clicking on the remove button, we check the selected users.
// When clicking on the remove button, we check the selected users.
// If you try to remove yourself, we'll display an additional warning message
// If you try to remove yourself, we'll display an additional warning message
var btnMsg = pending ? 'Remove pending owners' : 'Remove owners' ; // XXX
var btnMsg = pending ? Messages . owner _removePendingButton : Messages . owner _removeButton ;
var removeButton = h ( 'button.no-margin' , btnMsg ) ;
var removeButton = h ( 'button.no-margin' , btnMsg ) ;
$ ( removeButton ) . click ( function ( ) {
$ ( removeButton ) . click ( function ( ) {
// Check selection
// Check selection
var $sel = $div . find ( '.cp-share-friend.cp-selected' ) ;
var $sel = $div . find ( '.cp-share-friend.cp-selected' ) ;
var sel = $sel . toArray ( ) ;
var sel = $sel . toArray ( ) ;
if ( ! sel . length ) { return ; }
var me = false ;
var me = false ;
var toRemove = sel . map ( function ( el ) {
var toRemove = sel . map ( function ( el ) {
var ed = $ ( el ) . attr ( 'data-ed' ) ;
var ed = $ ( el ) . attr ( 'data-ed' ) ;
@ -197,25 +169,54 @@ define([
if ( ed === edPublic ) { me = true ; }
if ( ed === edPublic ) { me = true ; }
return ed ;
return ed ;
} ) . filter ( function ( x ) { return x ; } ) ;
} ) . filter ( function ( x ) { return x ; } ) ;
NThen ( function ( waitFor ) {
var msg = me ? Messages . owner _removeMeConfirm : Messages . owner _removeConfirm ;
UI . confirm ( msg , waitFor ( function ( yes ) {
if ( ! yes ) {
waitFor . abort ( ) ;
return ;
}
} ) ) ;
} ) . nThen ( function ( waitFor ) {
// Send the command
// Send the command
var send = function ( ) {
sframeChan . query ( 'Q_SET_PAD_METADATA' , {
sframeChan . query ( 'Q_SET_PAD_METADATA' , {
channel : channel ,
channel : channel ,
command : pending ? 'RM_PENDING_OWNERS' : 'RM_OWNERS' ,
command : pending ? 'RM_PENDING_OWNERS' : 'RM_OWNERS' ,
value : toRemove
value : toRemove
} , function ( err , res ) {
} , waitFor ( function ( err , res ) {
err = err || ( res && res . error ) ;
err = err || ( res && res . error ) ;
if ( err ) { return void UI . warn ( 'ERROR' + err ) ; } // XXX
if ( err ) {
waitFor . abort ( ) ;
redrawAll ( ) ;
redrawAll ( ) ;
UI . log ( 'DONE' ) ; // XXX
var text = err === "INSUFFICIENT_PERMISSIONS" ? Messages . fm _forbidden
: Messages . error ;
return void UI . warn ( text ) ;
}
UI . log ( Messages . saved ) ;
} ) ) ;
} ) . nThen ( function ( waitFor ) {
sel . forEach ( function ( el ) {
var friend = friends [ $ ( el ) . attr ( 'data-curve' ) ] ;
if ( ! friend ) { return ; }
common . mailbox . sendTo ( "RM_OWNER" , {
channel : channel ,
title : data . title ,
pending : pending ,
user : {
displayName : user . name ,
avatar : user . avatar ,
profile : user . profile ,
notifications : user . notifications ,
curvePublic : user . curvePublic ,
edPublic : priv . edPublic
}
} , {
channel : friend . notifications ,
curvePublic : friend . curvePublic
} , waitFor ( ) ) ;
} ) ;
} ) ;
} ;
} ) . nThen ( function ( ) {
var msg = me ?
redrawAll ( ) ;
"Are you sure? You're going to give up on your rights, this can't be undone!" :
"Are you sure?" ; // XXX
UI . confirm ( msg , function ( yes ) {
if ( ! yes ) { return ; }
send ( ) ;
} ) ;
} ) ;
} ) ;
} ) ;
$div . append ( h ( 'p' , removeButton ) ) ;
$div . append ( h ( 'p' , removeButton ) ) ;
@ -226,16 +227,16 @@ define([
var drawAdd = function ( ) {
var drawAdd = function ( ) {
var _friends = JSON . parse ( JSON . stringify ( friends ) ) ;
var _friends = JSON . parse ( JSON . stringify ( friends ) ) ;
Object . keys ( _friends ) . forEach ( function ( curve ) {
Object . keys ( _friends ) . forEach ( function ( curve ) {
if ( owners . indexOf ( _friends [ curve ] . edPublic ) !== - 1 ) {
if ( owners . indexOf ( _friends [ curve ] . edPublic ) !== - 1 ||
pending _owners . indexOf ( _friends [ curve ] . edPublic ) !== - 1 ) {
delete _friends [ curve ] ;
delete _friends [ curve ] ;
}
}
} ) ;
} ) ;
var addCol = UIElements . getFriendsList ( 'Ask a friend to be an owner.' , {
var addCol = UIElements . getFriendsList ( Messages . owner _addText , {
common : common ,
common : common ,
friends : _friends
friends : _friends
} , function ( ) {
} , function ( ) {
// XXX onSelect...
//console.log(arguments);
console . log ( arguments ) ;
} ) ;
} ) ;
$div2 = $ ( addCol . div ) ;
$div2 = $ ( addCol . div ) ;
var others2 = addCol . others ;
var others2 = addCol . others ;
@ -249,20 +250,20 @@ define([
order = order ? 'order:' + order : '' ;
order = order ? 'order:' + order : '' ;
$ ( this ) . removeClass ( 'cp-selected' ) . attr ( 'style' , order ) ;
$ ( this ) . removeClass ( 'cp-selected' ) . attr ( 'style' , order ) ;
}
}
// XXX onSelect...
} ) ;
} ) ;
// When clicking on the add button, we get the selected users.
// When clicking on the add button, we get the selected users.
var addButton = h ( 'button.no-margin' , 'Add owners' ) ; // XXX
var addButton = h ( 'button.no-margin' , Messages . owner _addButton ) ;
$ ( addButton ) . click ( function ( ) {
$ ( addButton ) . click ( function ( ) {
// Check selection
// Check selection
var $sel = $div2 . find ( '.cp-share-friend.cp-selected' ) ;
var $sel = $div2 . find ( '.cp-share-friend.cp-selected' ) ;
var sel = $sel . toArray ( ) ;
var sel = $sel . toArray ( ) ;
if ( ! sel . length ) { return ; }
var toAdd = sel . map ( function ( el ) {
var toAdd = sel . map ( function ( el ) {
return friends [ $ ( el ) . attr ( 'data-curve' ) ] . edPublic ;
return friends [ $ ( el ) . attr ( 'data-curve' ) ] . edPublic ;
} ) . filter ( function ( x ) { return x ; } ) ;
} ) . filter ( function ( x ) { return x ; } ) ;
NThen ( function ( waitFor ) {
NThen ( function ( waitFor ) {
var msg = "Are you sure?" ; // XXX
var msg = Messages . owner _addConfirm ;
UI . confirm ( msg , waitFor ( function ( yes ) {
UI . confirm ( msg , waitFor ( function ( yes ) {
if ( ! yes ) {
if ( ! yes ) {
waitFor . abort ( ) ;
waitFor . abort ( ) ;
@ -270,23 +271,22 @@ define([
}
}
} ) ) ;
} ) ) ;
} ) . nThen ( function ( waitFor ) {
} ) . nThen ( function ( waitFor ) {
console . log ( 'koko' ) ;
// Send the command
// Send the command
sframeChan . query ( 'Q_SET_PAD_METADATA' , {
sframeChan . query ( 'Q_SET_PAD_METADATA' , {
channel : channel ,
channel : channel ,
command : 'ADD_PENDING_OWNERS' ,
command : 'ADD_PENDING_OWNERS' ,
value : toAdd
value : toAdd
} , waitFor ( function ( err , res ) {
} , waitFor ( function ( err , res ) {
console . error ( arguments ) ;
err = err || ( res && res . error ) ;
err = err || ( res && res . error ) ;
if ( err ) {
if ( err ) {
waitFor . abort ( ) ;
waitFor . abort ( ) ;
return void UI . warn ( 'ERROR' + err ) ;
redrawAll ( ) ;
} // XXX
var text = err === "INSUFFICIENT_PERMISSIONS" ? Messages . fm _forbidden
: Messages . error ;
return void UI . warn ( text ) ;
}
} ) ) ;
} ) ) ;
} ) . nThen ( function ( waitFor ) {
} ) . nThen ( function ( waitFor ) {
console . log ( 'okok' ) ;
// TODO send notifications
sel . forEach ( function ( el ) {
sel . forEach ( function ( el ) {
var friend = friends [ $ ( el ) . attr ( 'data-curve' ) ] ;
var friend = friends [ $ ( el ) . attr ( 'data-curve' ) ] ;
if ( ! friend ) { return ; }
if ( ! friend ) { return ; }
@ -310,28 +310,42 @@ define([
} ) ;
} ) ;
} ) . nThen ( function ( ) {
} ) . nThen ( function ( ) {
redrawAll ( ) ;
redrawAll ( ) ;
UI . log ( 'DONE' ) ; // XXX
UI . log ( Messages . saved ) ;
} ) ;
} ) ;
} ) ;
} ) ;
$div2 . append ( h ( 'p' , addButton ) ) ;
$div2 . append ( h ( 'p' , addButton ) ) ;
return $div2 ;
return $div2 ;
} ;
} ;
redrawAll = function ( ) {
redrawAll = function ( md ) {
var todo = function ( obj ) {
if ( obj && obj . error ) { return ; }
owners = obj . owners || [ ] ;
pending _owners = obj . pending _owners || [ ] ;
$div1 . empty ( ) ;
$div1 . empty ( ) ;
$div2 . empty ( ) ;
$div2 . empty ( ) ;
common . getPadMetadata ( null , function ( obj ) {
if ( obj && obj . error ) { return ; }
owners = obj . owners ;
pending _owners = obj . pending _owners ;
$div1 . append ( drawRemove ( false ) ) . append ( drawRemove ( true ) ) ;
$div1 . append ( drawRemove ( false ) ) . append ( drawRemove ( true ) ) ;
$div2 . append ( drawAdd ( ) ) ;
$div2 . append ( drawAdd ( ) ) ;
} ) ;
} ;
if ( md ) { return void todo ( md ) ; }
common . getPadMetadata ( {
channel : data . channel
} , todo ) ;
} ;
} ;
$div1 . append ( drawRemove ( false ) ) . append ( drawRemove ( true ) ) ;
$div1 . append ( drawRemove ( false ) ) . append ( drawRemove ( true ) ) ;
$div2 . append ( drawAdd ( ) ) ;
$div2 . append ( drawAdd ( ) ) ;
var handler = sframeChan . on ( 'EV_RT_METADATA' , function ( md ) {
if ( ! $div1 . length ) {
return void handler . stop ( ) ;
}
owners = md . owners || [ ] ;
pending _owners = md . pending _owners || [ ] ;
redrawAll ( md ) ;
} ) ;
// Create modal
// Create modal
var link = h ( 'div.cp-share-columns' , [
var link = h ( 'div.cp-share-columns' , [
div1 ,
div1 ,
@ -341,16 +355,18 @@ define([
] ) ;
] ) ;
var linkButtons = [ {
var linkButtons = [ {
className : 'cancel' ,
className : 'cancel' ,
name : 'CLOSE' , // XXX existing key?
name : Messages . filePicker _close ,
onClick : function ( ) { } ,
onClick : function ( ) { } ,
keys : [ 27 ]
keys : [ 27 ]
} ] ;
} ] ;
return UI . dialog . customModal ( link , { buttons : linkButtons } ) ;
return UI . dialog . customModal ( link , { buttons : linkButtons } ) ;
} ;
} ;
var getRightsProperties = function ( common , data , cb ) {
var getRightsProperties = function ( common , data , cb ) {
var $d = $ ( '<div>' ) ;
var $d iv = $ ( '<div>' ) ;
if ( ! data ) { return void cb ( void 0 , $d ) ; }
if ( ! data ) { return void cb ( void 0 , $d iv ) ; }
var draw = function ( ) {
var $d = $ ( '<div>' ) ;
$ ( '<label>' , { 'for' : 'cp-app-prop-owners' } ) . text ( Messages . creation _owners )
$ ( '<label>' , { 'for' : 'cp-app-prop-owners' } ) . text ( Messages . creation _owners )
. appendTo ( $d ) ;
. appendTo ( $d ) ;
var owners = Messages . creation _noOwner ;
var owners = Messages . creation _noOwner ;
@ -388,7 +404,7 @@ define([
id : 'cp-app-prop-owners' ,
id : 'cp-app-prop-owners' ,
} ) ) ;
} ) ) ;
if ( owned ) {
if ( owned ) {
var manageOwners = h ( 'button.no-margin' , 'Manage owners' ) ; // XXX
var manageOwners = h ( 'button.no-margin' , Messages . owner _openModalButton ) ;
$ ( manageOwners ) . click ( function ( ) {
$ ( manageOwners ) . click ( function ( ) {
var modal = createOwnerModal ( common , data ) ;
var modal = createOwnerModal ( common , data ) ;
UI . openCustomModal ( modal , {
UI . openCustomModal ( modal , {
@ -479,8 +495,25 @@ define([
$d . append ( changePass ) ;
$d . append ( changePass ) ;
}
}
}
}
return $d ;
} ;
cb ( void 0 , $d ) ;
var sframeChan = common . getSframeChannel ( ) ;
var handler = sframeChan . on ( 'EV_RT_METADATA' , function ( md ) {
if ( ! $div . length ) {
handler . stop ( ) ;
return ;
}
md = JSON . parse ( JSON . stringify ( md ) ) ;
data . owners = md . owners ;
data . expire = md . expire ;
data . pending _owners = md . pending _owners ;
$div . empty ( ) ;
$div . append ( draw ( ) ) ;
} ) ;
$div . append ( draw ( ) ) ;
cb ( void 0 , $div ) ;
} ;
} ;
var getPadProperties = function ( common , data , cb ) {
var getPadProperties = function ( common , data , cb ) {
var $d = $ ( '<div>' ) ;
var $d = $ ( '<div>' ) ;
@ -567,6 +600,8 @@ define([
} else {
} else {
cb ( void 0 , $d ) ;
cb ( void 0 , $d ) ;
}
}
} ;
} ;
UIElements . getProperties = function ( common , data , cb ) {
UIElements . getProperties = function ( common , data , cb ) {
var c1 ;
var c1 ;
@ -3068,6 +3103,7 @@ define([
} ;
} ;
var storePopupState = false ;
var storePopupState = false ;
var autoStoreModal = { } ;
UIElements . displayStorePadPopup = function ( common , data ) {
UIElements . displayStorePadPopup = function ( common , data ) {
if ( storePopupState ) { return ; }
if ( storePopupState ) { return ; }
storePopupState = true ;
storePopupState = true ;
@ -3087,6 +3123,8 @@ define([
var initialHide = data && data . autoStore && data . autoStore === - 1 ;
var initialHide = data && data . autoStore && data . autoStore === - 1 ;
var modal = UI . cornerPopup ( text , actions , footer , { hidden : initialHide } ) ;
var modal = UI . cornerPopup ( text , actions , footer , { hidden : initialHide } ) ;
autoStoreModal [ priv . channel ] = modal ;
$ ( modal . popup ) . find ( '.cp-corner-footer a' ) . click ( function ( e ) {
$ ( modal . popup ) . find ( '.cp-corner-footer a' ) . click ( function ( e ) {
e . preventDefault ( ) ;
e . preventDefault ( ) ;
common . openURL ( '/settings/' ) ;
common . openURL ( '/settings/' ) ;
@ -3094,6 +3132,7 @@ define([
$ ( hide ) . click ( function ( ) {
$ ( hide ) . click ( function ( ) {
UIElements . displayCrowdfunding ( common ) ;
UIElements . displayCrowdfunding ( common ) ;
delete autoStoreModal [ priv . channel ] ;
modal . delete ( ) ;
modal . delete ( ) ;
} ) ;
} ) ;
var waitingForStoringCb = false ;
var waitingForStoringCb = false ;
@ -3109,6 +3148,7 @@ define([
}
}
return void UI . warn ( Messages . autostore _error ) ;
return void UI . warn ( Messages . autostore _error ) ;
}
}
delete autoStoreModal [ priv . channel ] ;
modal . delete ( ) ;
modal . delete ( ) ;
UIElements . displayCrowdfunding ( common ) ;
UIElements . displayCrowdfunding ( common ) ;
UI . log ( Messages . autostore _saved ) ;
UI . log ( Messages . autostore _saved ) ;
@ -3286,7 +3326,6 @@ define([
var name = Util . fixHTML ( msg . content . user . displayName ) || Messages . anonymous ;
var name = Util . fixHTML ( msg . content . user . displayName ) || Messages . anonymous ;
var title = Util . fixHTML ( msg . content . title ) ;
var title = Util . fixHTML ( msg . content . title ) ;
Messages . owner _add = '{0} wants you to be an owner of the pad <b>{1}</b>. Do you accept?' ; //XXX
var text = Messages . _getKey ( 'owner_add' , [ name , title ] ) ;
var text = Messages . _getKey ( 'owner_add' , [ name , title ] ) ;
var link = h ( 'a' , {
var link = h ( 'a' , {
@ -3343,13 +3382,32 @@ define([
} , function ( err , res ) {
} , function ( err , res ) {
err = err || ( res && res . error ) ;
err = err || ( res && res . error ) ;
if ( err ) {
if ( err ) {
return void UI . warn ( 'ERROR ' + err ) ;
var text = err === "INSUFFICIENT_PERMISSIONS" ? Messages . fm _forbidden
} // XXX
: Messages . error ;
UI . log ( 'DONE' ) ; // XXX
return void UI . warn ( text ) ;
}
UI . log ( Messages . saved ) ;
// Send notification to the sender
// Send notification to the sender
answer ( true ) ;
answer ( true ) ;
var data = JSON . parse ( JSON . stringify ( msg . content ) ) ;
data . metadata = res ;
// Add the pad to your drive
// This command will also add your mailbox to the metadata log
// The callback is called when the pad is stored, independantly of the metadata command
sframeChan . query ( 'Q_ACCEPT_OWNERSHIP' , data , function ( err , res ) {
if ( err || ( res && res . error ) ) {
return void console . error ( err | res . error ) ;
}
UI . log ( Messages . saved ) ;
if ( autoStoreModal [ data . channel ] ) {
autoStoreModal [ data . channel ] . delete ( ) ;
delete autoStoreModal [ data . channel ] ;
}
} ) ;
// Remove yourself from the pending owners
// Remove yourself from the pending owners
sframeChan . query ( 'Q_SET_PAD_METADATA' , {
sframeChan . query ( 'Q_SET_PAD_METADATA' , {
channel : msg . content . channel ,
channel : msg . content . channel ,