@ -39586,441 +39586,445 @@ var TextSecureServer = (function() {
* vim : ts = 4 : sw = 4 : expandtab
* /
// sendMessage(numbers = [], message = PushMessageContentProto, callback(success/failure map))
window . textsecure . messaging = function ( ) {
'use strict' ;
var self = { } ;
// message == DataMessage or ContentMessage proto
function sendMessageToDevices ( timestamp , number , deviceObjectList , message ) {
var relay = deviceObjectList [ 0 ] . relay ;
for ( var i = 1 ; i < deviceObjectList . length ; ++ i ) {
if ( deviceObjectList [ i ] . relay !== relay ) {
throw new Error ( "Mismatched relays for number " + number ) ;
window . textsecure . MessageSender = function ( url , username , password ) {
'use strict' ;
var server = new TextSecureServer ( url , username , password ) ;
return ( function ( TextSecureServer ) {
'use strict' ;
var self = { } ;
// message == DataMessage or ContentMessage proto
function sendMessageToDevices ( timestamp , number , deviceObjectList , message ) {
var relay = deviceObjectList [ 0 ] . relay ;
for ( var i = 1 ; i < deviceObjectList . length ; ++ i ) {
if ( deviceObjectList [ i ] . relay !== relay ) {
throw new Error ( "Mismatched relays for number " + number ) ;
}
}
}
return Promise . all ( deviceObjectList . map ( function ( device ) {
return textsecure . protocol _wrapper . encryptMessageFor ( device , message ) . then ( function ( encryptedMsg ) {
return textsecure . protocol _wrapper . getRegistrationId ( device . encodedNumber ) . then ( function ( registrationId ) {
return textsecure . storage . devices . removeTempKeysFromDevice ( device . encodedNumber ) . then ( function ( ) {
var json = {
type : encryptedMsg . type ,
destinationDeviceId : textsecure . utils . unencodeNumber ( device . encodedNumber ) [ 1 ] ,
destinationRegistrationId : registrationId ,
content : encryptedMsg . body ,
timestamp : timestamp
} ;
return Promise . all ( deviceObjectList . map ( function ( device ) {
return textsecure . protocol _wrapper . encryptMessageFor ( device , message ) . then ( function ( encryptedMsg ) {
return textsecure . protocol _wrapper . getRegistrationId ( device . encodedNumber ) . then ( function ( registrationId ) {
return textsecure . storage . devices . removeTempKeysFromDevice ( device . encodedNumber ) . then ( function ( ) {
var json = {
type : encryptedMsg . type ,
destinationDeviceId : textsecure . utils . unencodeNumber ( device . encodedNumber ) [ 1 ] ,
destinationRegistrationId : registrationId ,
content : encryptedMsg . body ,
timestamp : timestamp
} ;
if ( device . relay !== undefined ) {
json . relay = device . relay ;
}
if ( device . relay !== undefined ) {
json . relay = device . relay ;
}
return json ;
return json ;
} ) ;
} ) ;
} ) ;
} ) ) . then ( function ( jsonData ) {
var legacy = ( message instanceof textsecure . protobuf . DataMessage ) ;
return TextSecureServer . sendMessages ( number , jsonData , legacy ) ;
} ) ;
} ) ) . then ( function ( jsonData ) {
var legacy = ( message instanceof textsecure . protobuf . DataMessage ) ;
return TextSecureServer . sendMessages ( number , jsonData , legacy ) ;
} ) ;
}
}
function makeAttachmentPointer ( attachment ) {
var proto = new textsecure . protobuf . AttachmentPointer ( ) ;
proto . key = textsecure . crypto . getRandomBytes ( 64 ) ;
function makeAttachmentPointer ( attachment ) {
var proto = new textsecure . protobuf . AttachmentPointer ( ) ;
proto . key = textsecure . crypto . getRandomBytes ( 64 ) ;
var iv = textsecure . crypto . getRandomBytes ( 16 ) ;
return textsecure . crypto . encryptAttachment ( attachment . data , proto . key , iv ) . then ( function ( encryptedBin ) {
return TextSecureServer . putAttachment ( encryptedBin ) . then ( function ( id ) {
proto . id = id ;
proto . contentType = attachment . contentType ;
return proto ;
var iv = textsecure . crypto . getRandomBytes ( 16 ) ;
return textsecure . crypto . encryptAttachment ( attachment . data , proto . key , iv ) . then ( function ( encryptedBin ) {
return TextSecureServer . putAttachment ( encryptedBin ) . then ( function ( id ) {
proto . id = id ;
proto . contentType = attachment . contentType ;
return proto ;
} ) ;
} ) ;
} ) ;
}
}
var tryMessageAgain = function ( number , encodedMessage , timestamp ) {
var proto = textsecure . protobuf . DataMessage . decode ( encodedMessage ) ;
return new Promise ( function ( resolve , reject ) {
sendMessageProto ( timestamp , [ number ] , proto , function ( res ) {
if ( res . failure . length > 0 )
reject ( res . failure ) ;
else
resolve ( ) ;
var tryMessageAgain = function ( number , encodedMessage , timestamp ) {
var proto = textsecure . protobuf . DataMessage . decode ( encodedMessage ) ;
return new Promise ( function ( resolve , reject ) {
sendMessageProto ( timestamp , [ number ] , proto , function ( res ) {
if ( res . failure . length > 0 )
reject ( res . failure ) ;
else
resolve ( ) ;
} ) ;
} ) ;
} ) ;
} ;
textsecure . replay . registerFunction ( tryMessageAgain , textsecure . replay . Type . SEND _MESSAGE ) ;
var sendMessageProto = function ( timestamp , numbers , message , callback ) {
var numbersCompleted = 0 ;
var errors = [ ] ;
var successfulNumbers = [ ] ;
var numberCompleted = function ( ) {
numbersCompleted ++ ;
if ( numbersCompleted >= numbers . length )
callback ( { success : successfulNumbers , failure : errors } ) ;
} ;
var registerError = function ( number , reason , error ) {
if ( ! error ) {
error = new Error ( reason ) ;
}
error . number = number ;
error . reason = reason ;
errors [ errors . length ] = error ;
numberCompleted ( ) ;
} ;
textsecure . replay . registerFunction ( tryMessageAgain , textsecure . replay . Type . SEND _MESSAGE ) ;
var reloadDevicesAndSend = function ( number , recurse ) {
return function ( ) {
return textsecure . storage . devices . getDeviceObjectsForNumber ( number ) . then ( function ( devicesForNumber ) {
if ( devicesForNumber . length == 0 )
return registerError ( number , "Got empty device list when loading device keys" , null ) ;
doSendMessage ( number , devicesForNumber , recurse ) ;
} ) ;
}
} ;
var sendMessageProto = function ( timestamp , numbers , message , callback ) {
var numbersCompleted = 0 ;
var errors = [ ] ;
var successfulNumbers = [ ] ;
function getKeysForNumber ( number , updateDevices ) {
var handleResult = function ( response ) {
return Promise . all ( response . devices . map ( function ( device ) {
if ( updateDevices === undefined || updateDevices . indexOf ( device . deviceId ) > - 1 )
return textsecure . storage . devices . saveKeysToDeviceObject ( {
encodedNumber : number + "." + device . deviceId ,
identityKey : response . identityKey ,
preKey : device . preKey . publicKey ,
preKeyId : device . preKey . keyId ,
signedKey : device . signedPreKey . publicKey ,
signedKeyId : device . signedPreKey . keyId ,
signedKeySignature : device . signedPreKey . signature ,
registrationId : device . registrationId
} ) . catch ( function ( error ) {
if ( error . message === "Identity key changed" ) {
error = new textsecure . OutgoingIdentityKeyError ( number , message . toArrayBuffer ( ) , timestamp , error . identityKey ) ;
registerError ( number , "Identity key changed" , error ) ;
}
throw error ;
} ) ;
} ) ) ;
var numberCompleted = function ( ) {
numbersCompleted ++ ;
if ( numbersCompleted >= numbers . length )
callback ( { success : successfulNumbers , failure : errors } ) ;
} ;
if ( updateDevices === undefined ) {
return TextSecureServer . getKeysForNumber ( number ) . then ( handleResult ) ;
} else {
var promises = [ ] ;
for ( var i in updateDevices )
promises [ promises . length ] = TextSecureServer . getKeysForNumber ( number , updateDevices [ i ] ) . then ( handleResult ) ;
return Promise . all ( promises ) ;
}
}
var doSendMessage = function ( number , devicesForNumber , recurse ) {
return sendMessageToDevices ( timestamp , number , devicesForNumber , message ) . then ( function ( result ) {
successfulNumbers [ successfulNumbers . length ] = number ;
var registerError = function ( number , reason , error ) {
if ( ! error ) {
error = new Error ( reason ) ;
}
error . number = number ;
error . reason = reason ;
errors [ errors . length ] = error ;
numberCompleted ( ) ;
} ) . catch ( function ( error ) {
if ( error instanceof Error && error . name == "HTTPError" && ( error . code == 410 || error . code == 409 ) ) {
if ( ! recurse )
return registerError ( number , "Hit retry limit attempting to reload device list" , error ) ;
var p ;
if ( error . code == 409 ) {
p = textsecure . storage . devices . removeDeviceIdsForNumber ( number , error . response . extraDevices ) ;
} else {
p = Promise . all ( error . response . staleDevices . map ( function ( deviceId ) {
return textsecure . protocol _wrapper . closeOpenSessionForDevice ( number + '.' + deviceId ) ;
} ) ) ;
}
} ;
p . then ( function ( ) {
var resetDevices = ( ( error . code == 410 ) ? error . response . staleDevices : error . response . missingDevices ) ;
getKeysForNumber ( number , resetDevices )
. then ( reloadDevicesAndSend ( number , ( error . code == 409 ) ) )
. catch ( function ( error ) {
registerError ( number , "Failed to reload device keys" , error ) ;
} ) ;
var reloadDevicesAndSend = function ( number , recurse ) {
return function ( ) {
return textsecure . storage . devices . getDeviceObjectsForNumber ( number ) . then ( function ( devicesForNumber ) {
if ( devicesForNumber . length == 0 )
return registerError ( number , "Got empty device list when loading device keys" , null ) ;
doSendMessage ( number , devicesForNumber , recurse ) ;
} ) ;
}
} ;
function getKeysForNumber ( number , updateDevices ) {
var handleResult = function ( response ) {
return Promise . all ( response . devices . map ( function ( device ) {
if ( updateDevices === undefined || updateDevices . indexOf ( device . deviceId ) > - 1 )
return textsecure . storage . devices . saveKeysToDeviceObject ( {
encodedNumber : number + "." + device . deviceId ,
identityKey : response . identityKey ,
preKey : device . preKey . publicKey ,
preKeyId : device . preKey . keyId ,
signedKey : device . signedPreKey . publicKey ,
signedKeyId : device . signedPreKey . keyId ,
signedKeySignature : device . signedPreKey . signature ,
registrationId : device . registrationId
} ) . catch ( function ( error ) {
if ( error . message === "Identity key changed" ) {
error = new textsecure . OutgoingIdentityKeyError ( number , message . toArrayBuffer ( ) , timestamp , error . identityKey ) ;
registerError ( number , "Identity key changed" , error ) ;
}
throw error ;
} ) ;
} ) ) ;
} ;
if ( updateDevices === undefined ) {
return TextSecureServer . getKeysForNumber ( number ) . then ( handleResult ) ;
} else {
registerError ( number , "Failed to create or send message" , error ) ;
var promises = [ ] ;
for ( var i in updateDevices )
promises [ promises . length ] = TextSecureServer . getKeysForNumber ( number , updateDevices [ i ] ) . then ( handleResult ) ;
return Promise . all ( promises ) ;
}
} ) ;
} ;
}
numbers . forEach ( function ( number ) {
textsecure . storage . devices . getDeviceObjectsForNumber ( number ) . then ( function ( devicesForNumber ) {
return Promise . all ( devicesForNumber . map ( function ( device ) {
return textsecure . protocol _wrapper . hasOpenSession ( device . encodedNumber ) . then ( function ( result ) {
if ( ! result )
return getKeysForNumber ( number , [ parseInt ( textsecure . utils . unencodeNumber ( device . encodedNumber ) [ 1 ] ) ] ) ;
} ) ;
} ) ) . then ( function ( ) {
return textsecure . storage . devices . getDeviceObjectsForNumber ( number ) . then ( function ( devicesForNumber ) {
if ( devicesForNumber . length == 0 ) {
getKeysForNumber ( number , [ 1 ] )
. then ( reloadDevicesAndSend ( number , true ) )
var doSendMessage = function ( number , devicesForNumber , recurse ) {
return sendMessageToDevices ( timestamp , number , devicesForNumber , message ) . then ( function ( result ) {
successfulNumbers [ successfulNumbers . length ] = number ;
numberCompleted ( ) ;
} ) . catch ( function ( error ) {
if ( error instanceof Error && error . name == "HTTPError" && ( error . code == 410 || error . code == 409 ) ) {
if ( ! recurse )
return registerError ( number , "Hit retry limit attempting to reload device list" , error ) ;
var p ;
if ( error . code == 409 ) {
p = textsecure . storage . devices . removeDeviceIdsForNumber ( number , error . response . extraDevices ) ;
} else {
p = Promise . all ( error . response . staleDevices . map ( function ( deviceId ) {
return textsecure . protocol _wrapper . closeOpenSessionForDevice ( number + '.' + deviceId ) ;
} ) ) ;
}
p . then ( function ( ) {
var resetDevices = ( ( error . code == 410 ) ? error . response . staleDevices : error . response . missingDevices ) ;
getKeysForNumber ( number , resetDevices )
. then ( reloadDevicesAndSend ( number , ( error . code == 409 ) ) )
. catch ( function ( error ) {
registerError ( number , "Failed to retreive new device keys for number " + number , error ) ;
registerError ( number , "Failed to re load device keys" , error ) ;
} ) ;
} else
doSendMessage ( number , devicesForNumber , true ) ;
} ) ;
} else {
registerError ( number , "Failed to create or send message" , error ) ;
}
} ) ;
} ;
numbers . forEach ( function ( number ) {
textsecure . storage . devices . getDeviceObjectsForNumber ( number ) . then ( function ( devicesForNumber ) {
return Promise . all ( devicesForNumber . map ( function ( device ) {
return textsecure . protocol _wrapper . hasOpenSession ( device . encodedNumber ) . then ( function ( result ) {
if ( ! result )
return getKeysForNumber ( number , [ parseInt ( textsecure . utils . unencodeNumber ( device . encodedNumber ) [ 1 ] ) ] ) ;
} ) ;
} ) ) . then ( function ( ) {
return textsecure . storage . devices . getDeviceObjectsForNumber ( number ) . then ( function ( devicesForNumber ) {
if ( devicesForNumber . length == 0 ) {
getKeysForNumber ( number , [ 1 ] )
. then ( reloadDevicesAndSend ( number , true ) )
. catch ( function ( error ) {
registerError ( number , "Failed to retreive new device keys for number " + number , error ) ;
} ) ;
} else
doSendMessage ( number , devicesForNumber , true ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
}
}
var sendIndividualProto = function ( number , proto , timestamp ) {
return new Promise ( function ( resolve , reject ) {
sendMessageProto ( timestamp , [ number ] , proto , function ( res ) {
if ( res . failure . length > 0 )
reject ( res . failure ) ;
else
resolve ( ) ;
var sendIndividualProto = function ( number , proto , timestamp ) {
return new Promise ( function ( resolve , reject ) {
sendMessageProto ( timestamp , [ number ] , proto , function ( res ) {
if ( res . failure . length > 0 )
reject ( res . failure ) ;
else
resolve ( ) ;
} ) ;
} ) ;
} ) ;
}
var sendSyncMessage = function ( message , timestamp , destination ) {
var myNumber = textsecure . storage . user . getNumber ( ) ;
var myDevice = textsecure . storage . user . getDeviceId ( ) ;
if ( myDevice != 1 ) {
var sentMessage = new textsecure . protobuf . SyncMessage . Sent ( ) ;
sentMessage . timestamp = timestamp ;
sentMessage . message = message ;
if ( destination ) {
sentMessage . destination = destination ;
}
var syncMessage = new textsecure . protobuf . SyncMessage ( ) ;
syncMessage . sent = sentMessage ;
var contentMessage = new textsecure . protobuf . Content ( ) ;
contentMessage . syncMessage = syncMessage ;
return sendIndividualProto ( myNumber , contentMessage , Date . now ( ) ) ;
}
}
self . sendRequestGroupSyncMessage = function ( ) {
var myNumber = textsecure . storage . user . getNumber ( ) ;
var myDevice = textsecure . storage . user . getDeviceId ( ) ;
if ( myDevice != 1 ) {
var request = new textsecure . protobuf . SyncMessage . Request ( ) ;
request . type = textsecure . protobuf . SyncMessage . Request . Type . GROUPS ;
var syncMessage = new textsecure . protobuf . SyncMessage ( ) ;
syncMessage . request = request ;
var contentMessage = new textsecure . protobuf . Content ( ) ;
contentMessage . syncMessage = syncMessage ;
var sendSyncMessage = function ( message , timestamp , destination ) {
var myNumber = textsecure . storage . user . getNumber ( ) ;
var myDevice = textsecure . storage . user . getDeviceId ( ) ;
if ( myDevice != 1 ) {
var sentMessage = new textsecure . protobuf . SyncMessage . Sent ( ) ;
sentMessage . timestamp = timestamp ;
sentMessage . message = message ;
if ( destination ) {
sentMessage . destination = destination ;
}
var syncMessage = new textsecure . protobuf . SyncMessage ( ) ;
syncMessage . sent = sentMessage ;
var contentMessage = new textsecure . protobuf . Content ( ) ;
contentMessage . syncMessage = syncMessage ;
return sendIndividualProto ( myNumber , contentMessage , Date . now ( ) ) ;
}
} ;
self . sendRequestContactSyncMessage = function ( ) {
var myNumber = textsecure . storage . user . getNumber ( ) ;
var myDevice = textsecure . storage . user . getDeviceId ( ) ;
if ( myDevice != 1 ) {
var request = new textsecure . protobuf . SyncMessage . Request ( ) ;
request . type = textsecure . protobuf . SyncMessage . Request . Type . CONTACTS ;
var syncMessage = new textsecure . protobuf . SyncMessage ( ) ;
syncMessage . request = request ;
var contentMessage = new textsecure . protobuf . Content ( ) ;
contentMessage . syncMessage = syncMessage ;
return sendIndividualProto ( myNumber , contentMessage , Date . now ( ) ) ;
return sendIndividualProto ( myNumber , contentMessage , Date . now ( ) ) ;
}
}
} ;
var sendGroupProto = function ( numbers , proto , timestamp ) {
timestamp = timestamp || Date . now ( ) ;
var me = textsecure . storage . user . getNumber ( ) ;
numbers = numbers . filter ( function ( number ) { return number != me ; } ) ;
self . sendRequestGroupSyncMessage = function ( ) {
var myNumber = textsecure . storage . user . getNumber ( ) ;
var myDevice = textsecure . storage . user . getDeviceId ( ) ;
if ( myDevice != 1 ) {
var request = new textsecure . protobuf . SyncMessage . Request ( ) ;
request . type = textsecure . protobuf . SyncMessage . Request . Type . GROUPS ;
var syncMessage = new textsecure . protobuf . SyncMessage ( ) ;
syncMessage . request = request ;
var contentMessage = new textsecure . protobuf . Content ( ) ;
contentMessage . syncMessage = syncMessage ;
return new Promise ( function ( resolve , reject ) {
sendMessageProto ( timestamp , numbers , proto , function ( res ) {
if ( res . failure . length > 0 )
reject ( res . failure ) ;
else
resolve ( ) ;
} ) ;
} ) . then ( function ( ) {
return sendSyncMessage ( proto , timestamp ) ;
} ) ;
}
return sendIndividualProto ( myNumber , contentMessage , Date . now ( ) ) ;
}
} ;
self . sendRequestContactSyncMessage = function ( ) {
var myNumber = textsecure . storage . user . getNumber ( ) ;
var myDevice = textsecure . storage . user . getDeviceId ( ) ;
if ( myDevice != 1 ) {
var request = new textsecure . protobuf . SyncMessage . Request ( ) ;
request . type = textsecure . protobuf . SyncMessage . Request . Type . CONTACTS ;
var syncMessage = new textsecure . protobuf . SyncMessage ( ) ;
syncMessage . request = request ;
var contentMessage = new textsecure . protobuf . Content ( ) ;
contentMessage . syncMessage = syncMessage ;
return sendIndividualProto ( myNumber , contentMessage , Date . now ( ) ) ;
}
} ;
self . sendMessageToNumber = function ( number , messageText , attachments , timestamp ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . body = messageText ;
var promises = [ ] ;
for ( var i in attachments )
promises . push ( makeAttachmentPointer ( attachments [ i ] ) ) ;
return Promise . all ( promises ) . then ( function ( attachmentsArray ) {
proto . attachments = attachmentsArray ;
return sendIndividualProto ( number , proto , timestamp ) . then ( function ( ) {
return sendSyncMessage ( proto , timestamp , number ) ;
} ) ;
} ) ;
}
var sendGroupProto = function ( numbers , proto , timestamp ) {
timestamp = timestamp || Date . now ( ) ;
var me = textsecure . storage . user . getNumber ( ) ;
numbers = numbers . filter ( function ( number ) { return number != me ; } ) ;
self . closeSession = function ( number ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . body = "TERMINATE" ;
proto . flags = textsecure . protobuf . DataMessage . Flags . END _SESSION ;
return sendIndividualProto ( number , proto , Date . now ( ) ) . then ( function ( res ) {
return textsecure . storage . devices . getDeviceObjectsForNumber ( number ) . then ( function ( devices ) {
return Promise . all ( devices . map ( function ( device ) {
return textsecure . protocol _wrapper . closeOpenSessionForDevice ( device . encodedNumber ) ;
} ) ) . then ( function ( ) {
return res ;
return new Promise ( function ( resolve , reject ) {
sendMessageProto ( timestamp , numbers , proto , function ( res ) {
if ( res . failure . length > 0 )
reject ( res . failure ) ;
else
resolve ( ) ;
} ) ;
} ) . then ( function ( ) {
return sendSyncMessage ( proto , timestamp ) ;
} ) ;
} ) ;
}
self . sendMessageToGroup = function ( groupId , messageText , attachments , timestamp ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . body = messageText ;
proto . group = new textsecure . protobuf . GroupContext ( ) ;
proto . group . id = toArrayBuffer ( groupId ) ;
proto . group . type = textsecure . protobuf . GroupContext . Type . DELIVER ;
}
return textsecure . storage . groups . getNumbers ( groupId ) . then ( function ( numbers ) {
if ( numbers === undefined )
return Promise . reject ( new Error ( "Unknown Group" ) ) ;
self . sendMessageToNumber = function ( number , messageText , attachments , timestamp ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . body = messageText ;
var promises = [ ] ;
for ( var i in attachments )
promises . push ( makeAttachmentPointer ( attachments [ i ] ) ) ;
return Promise . all ( promises ) . then ( function ( attachmentsArray ) {
proto . attachments = attachmentsArray ;
return sendGroupProto ( numbers , proto , timestamp ) ;
return sendIndividualProto ( number , proto , timestamp ) . then ( function ( ) {
return sendSyncMessage ( proto , timestamp , number ) ;
} ) ;
} ) ;
} ) ;
}
}
self . createGroup = function ( numbers , name , avatar ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . group = new textsecure . protobuf . GroupContext ( ) ;
self . closeSession = function ( number ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . body = "TERMINATE" ;
proto . flags = textsecure . protobuf . DataMessage . Flags . END _SESSION ;
return sendIndividualProto ( number , proto , Date . now ( ) ) . then ( function ( res ) {
return textsecure . storage . devices . getDeviceObjectsForNumber ( number ) . then ( function ( devices ) {
return Promise . all ( devices . map ( function ( device ) {
return textsecure . protocol _wrapper . closeOpenSessionForDevice ( device . encodedNumber ) ;
} ) ) . then ( function ( ) {
return res ;
} ) ;
} ) ;
} ) ;
}
return textsecure . storage . groups . createNewGroup ( numbers ) . then ( function ( group ) {
proto . group . id = toArrayBuffer ( group . id ) ;
var numbers = group . numbers ;
self . sendMessageToGroup = function ( groupId , messageText , attachments , timestamp ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . body = messageText ;
proto . group = new textsecure . protobuf . GroupContext ( ) ;
proto . group . id = toArrayBuffer ( groupId ) ;
proto . group . type = textsecure . protobuf . GroupContext . Type . DELIVER ;
proto . group . type = textsecure . protobuf . GroupContext . Type . UPDATE ;
proto . group . members = numbers ;
proto . group . name = name ;
return textsecure . storage . groups . getNumbers ( groupId ) . then ( function ( numbers ) {
if ( numbers === undefined )
return Promise . reject ( new Error ( "Unknown Group" ) ) ;
if ( avatar !== undefined ) {
return makeAttachmentPointer ( avatar ) . then ( function ( attachment ) {
proto . group . avatar = attachment ;
var promises = [ ] ;
for ( var i in attachments )
promises . push ( makeAttachmentPointer ( attachments [ i ] ) ) ;
return Promise . all ( promises ) . then ( function ( attachmentsArray ) {
proto . attachments = attachmentsArray ;
return sendGroupProto ( numbers , proto , timestamp ) ;
} ) ;
} ) ;
}
self . createGroup = function ( numbers , name , avatar ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . group = new textsecure . protobuf . GroupContext ( ) ;
return textsecure . storage . groups . createNewGroup ( numbers ) . then ( function ( group ) {
proto . group . id = toArrayBuffer ( group . id ) ;
var numbers = group . numbers ;
proto . group . type = textsecure . protobuf . GroupContext . Type . UPDATE ;
proto . group . members = numbers ;
proto . group . name = name ;
if ( avatar !== undefined ) {
return makeAttachmentPointer ( avatar ) . then ( function ( attachment ) {
proto . group . avatar = attachment ;
return sendGroupProto ( numbers , proto ) . then ( function ( ) {
return proto . group . id ;
} ) ;
} ) ;
} else {
return sendGroupProto ( numbers , proto ) . then ( function ( ) {
return proto . group . id ;
} ) ;
} ) ;
} else {
return sendGroupProto ( numbers , proto ) . then ( function ( ) {
return proto . group . id ;
} ) ;
}
} ) ;
}
}
} ) ;
}
self . updateGroup = function ( groupId , name , avatar , numbers ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . group = new textsecure . protobuf . GroupContext ( ) ;
self . updateGroup = function ( groupId , name , avatar , numbers ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . group = new textsecure . protobuf . GroupContext ( ) ;
proto . group . id = toArrayBuffer ( groupId ) ;
proto . group . type = textsecure . protobuf . GroupContext . Type . UPDATE ;
proto . group . name = name ;
proto . group . id = toArrayBuffer ( groupId ) ;
proto . group . type = textsecure . protobuf . GroupContext . Type . UPDATE ;
proto . group . name = name ;
return textsecure . storage . groups . addNumbers ( groupId , numbers ) . then ( function ( numbers ) {
if ( numbers === undefined ) {
return Promise . reject ( new Error ( "Unknown Group" ) ) ;
}
proto . group . members = numbers ;
return textsecure . storage . groups . addNumbers ( groupId , numbers ) . then ( function ( numbers ) {
if ( numbers === undefined ) {
return Promise . reject ( new Error ( "Unknown Group" ) ) ;
}
proto . group . members = numbers ;
if ( avatar !== undefined && avatar !== null ) {
return makeAttachmentPointer ( avatar ) . then ( function ( attachment ) {
proto . group . avatar = attachment ;
if ( avatar !== undefined && avatar !== null ) {
return makeAttachmentPointer ( avatar ) . then ( function ( attachment ) {
proto . group . avatar = attachment ;
return sendGroupProto ( numbers , proto ) . then ( function ( ) {
return proto . group . id ;
} ) ;
} ) ;
} else {
return sendGroupProto ( numbers , proto ) . then ( function ( ) {
return proto . group . id ;
} ) ;
} ) ;
} else {
return sendGroupProto ( numbers , proto ) . then ( function ( ) {
return proto . group . id ;
} ) ;
}
} ) ;
}
}
} ) ;
}
self . addNumberToGroup = function ( groupId , number ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . group = new textsecure . protobuf . GroupContext ( ) ;
proto . group . id = toArrayBuffer ( groupId ) ;
proto . group . type = textsecure . protobuf . GroupContext . Type . UPDATE ;
self . addNumberToGroup = function ( groupId , number ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . group = new textsecure . protobuf . GroupContext ( ) ;
proto . group . id = toArrayBuffer ( groupId ) ;
proto . group . type = textsecure . protobuf . GroupContext . Type . UPDATE ;
return textsecure . storage . groups . addNumbers ( groupId , [ number ] ) . then ( function ( numbers ) {
if ( numbers === undefined )
return Promise . reject ( new Error ( "Unknown Group" ) ) ;
proto . group . members = numbers ;
return textsecure . storage . groups . addNumbers ( groupId , [ number ] ) . then ( function ( numbers ) {
if ( numbers === undefined )
return Promise . reject ( new Error ( "Unknown Group" ) ) ;
proto . group . members = numbers ;
return sendGroupProto ( numbers , proto ) ;
} ) ;
}
return sendGroupProto ( numbers , proto ) ;
} ) ;
}
self . setGroupName = function ( groupId , name ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . group = new textsecure . protobuf . GroupContext ( ) ;
proto . group . id = toArrayBuffer ( groupId ) ;
proto . group . type = textsecure . protobuf . GroupContext . Type . UPDATE ;
proto . group . name = name ;
self . setGroupName = function ( groupId , name ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . group = new textsecure . protobuf . GroupContext ( ) ;
proto . group . id = toArrayBuffer ( groupId ) ;
proto . group . type = textsecure . protobuf . GroupContext . Type . UPDATE ;
proto . group . name = name ;
return textsecure . storage . groups . getNumbers ( groupId ) . then ( function ( numbers ) {
if ( numbers === undefined )
return Promise . reject ( new Error ( "Unknown Group" ) ) ;
proto . group . members = numbers ;
return textsecure . storage . groups . getNumbers ( groupId ) . then ( function ( numbers ) {
if ( numbers === undefined )
return Promise . reject ( new Error ( "Unknown Group" ) ) ;
proto . group . members = numbers ;
return sendGroupProto ( numbers , proto ) ;
} ) ;
}
return sendGroupProto ( numbers , proto ) ;
} ) ;
}
self . setGroupAvatar = function ( groupId , avatar ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . group = new textsecure . protobuf . GroupContext ( ) ;
proto . group . id = toArrayBuffer ( groupId ) ;
proto . group . type = textsecure . protobuf . GroupContext . Type . UPDATE ;
self . setGroupAvatar = function ( groupId , avatar ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . group = new textsecure . protobuf . GroupContext ( ) ;
proto . group . id = toArrayBuffer ( groupId ) ;
proto . group . type = textsecure . protobuf . GroupContext . Type . UPDATE ;
return textsecure . storage . groups . getNumbers ( groupId ) . then ( function ( numbers ) {
if ( numbers === undefined )
return Promise . reject ( new Error ( "Unknown Group" ) ) ;
proto . group . members = numbers ;
return textsecure . storage . groups . getNumbers ( groupId ) . then ( function ( numbers ) {
if ( numbers === undefined )
return Promise . reject ( new Error ( "Unknown Group" ) ) ;
proto . group . members = numbers ;
return makeAttachmentPointer ( avatar ) . then ( function ( attachment ) {
proto . group . avatar = attachment ;
return sendGroupProto ( numbers , proto ) ;
return makeAttachmentPointer ( avatar ) . then ( function ( attachment ) {
proto . group . avatar = attachment ;
return sendGroupProto ( numbers , proto ) ;
} ) ;
} ) ;
} ) ;
}
}
self . leaveGroup = function ( groupId ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . group = new textsecure . protobuf . GroupContext ( ) ;
proto . group . id = toArrayBuffer ( groupId ) ;
proto . group . type = textsecure . protobuf . GroupContext . Type . QUIT ;
self . leaveGroup = function ( groupId ) {
var proto = new textsecure . protobuf . DataMessage ( ) ;
proto . group = new textsecure . protobuf . GroupContext ( ) ;
proto . group . id = toArrayBuffer ( groupId ) ;
proto . group . type = textsecure . protobuf . GroupContext . Type . QUIT ;
return textsecure . storage . groups . getNumbers ( groupId ) . then ( function ( numbers ) {
if ( numbers === undefined )
return Promise . reject ( new Error ( "Unknown Group" ) ) ;
return textsecure . storage . groups . deleteGroup ( groupId ) . then ( function ( ) {
return sendGroupProto ( numbers , proto ) ;
return textsecure . storage . groups . getNumbers ( groupId ) . then ( function ( numbers ) {
if ( numbers === undefined )
return Promise . reject ( new Error ( "Unknown Group" ) ) ;
return textsecure . storage . groups . deleteGroup ( groupId ) . then ( function ( ) {
return sendGroupProto ( numbers , proto ) ;
} ) ;
} ) ;
} ) ;
}
}
return self ;
} ( ) ;
return self ;
} ) ( server ) ;
} ;
/ *
* vim : ts = 4 : sw = 4 : expandtab