"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "ts/textsecure/SendMessage.ts" between
Signal-Desktop-1.35.2.tar.gz and Signal-Desktop-1.36.1.tar.gz

About: Signal-Desktop is a cross-platform encrypted messaging service (also available for mobile devices).

SendMessage.ts  (Signal-Desktop-1.35.2):SendMessage.ts  (Signal-Desktop-1.36.1)
// tslint:disable no-bitwise no-default-export // tslint:disable no-bitwise no-default-export
import { without } from 'lodash'; import { Dictionary, without } from 'lodash';
import PQueue from 'p-queue'; import PQueue from 'p-queue';
import { ProxiedRequestOptionsType, WebAPIType } from './WebAPI'; import {
GroupCredentialsType,
GroupLogResponseType,
ProxiedRequestOptionsType,
WebAPIType,
} from './WebAPI';
import createTaskWithTimeout from './TaskWithTimeout'; import createTaskWithTimeout from './TaskWithTimeout';
import OutgoingMessage from './OutgoingMessage'; import OutgoingMessage from './OutgoingMessage';
import Crypto from './Crypto'; import Crypto from './Crypto';
import { import {
base64ToArrayBuffer,
concatenateBytes,
fromEncodedBinaryToArrayBuffer,
getZeroes,
hexToArrayBuffer,
} from '../Crypto';
import {
AttachmentPointerClass, AttachmentPointerClass,
CallingMessageClass, CallingMessageClass,
ContentClass, ContentClass,
DataMessageClass, DataMessageClass,
GroupChangeClass,
GroupClass,
StorageServiceCallOptionsType, StorageServiceCallOptionsType,
StorageServiceCredentials, StorageServiceCredentials,
} from '../textsecure.d'; } from '../textsecure.d';
import { MessageError, SignedPreKeyRotationError } from './Errors'; import { MessageError, SignedPreKeyRotationError } from './Errors';
function stringToArrayBuffer(str: string): ArrayBuffer { function stringToArrayBuffer(str: string): ArrayBuffer {
if (typeof str !== 'string') { if (typeof str !== 'string') {
throw new Error('Passed non-string to stringToArrayBuffer'); throw new Error('Passed non-string to stringToArrayBuffer');
} }
const res = new ArrayBuffer(str.length); const res = new ArrayBuffer(str.length);
const uint = new Uint8Array(res); const uint = new Uint8Array(res);
for (let i = 0; i < str.length; i += 1) { for (let i = 0; i < str.length; i += 1) {
uint[i] = str.charCodeAt(i); uint[i] = str.charCodeAt(i);
} }
return res; return res;
} }
function hexStringToArrayBuffer(string: string): ArrayBuffer {
return window.dcodeIO.ByteBuffer.wrap(string, 'hex').toArrayBuffer();
}
function base64ToArrayBuffer(string: string): ArrayBuffer {
return window.dcodeIO.ByteBuffer.wrap(string, 'base64').toArrayBuffer();
}
export type SendMetadataType = { export type SendMetadataType = {
[identifier: string]: { [identifier: string]: {
accessKey: string; accessKey: string;
}; };
}; };
export type SendOptionsType = { export type SendOptionsType = {
senderCertificate?: ArrayBuffer; senderCertificate?: ArrayBuffer;
sendMetadata?: SendMetadataType; sendMetadata?: SendMetadataType;
online?: boolean; online?: boolean;
}; };
export type CallbackResultType = { export type CallbackResultType = {
successfulIdentifiers?: Array<any>; successfulIdentifiers?: Array<any>;
failoverIdentifiers?: Array<any>; failoverIdentifiers?: Array<any>;
errors?: Array<any>; errors?: Array<any>;
unidentifiedDeliveries?: Array<any>; unidentifiedDeliveries?: Array<any>;
dataMessage?: ArrayBuffer; dataMessage?: ArrayBuffer;
discoveredIdentifierPairs: Array<{
e164: string;
uuid: string | null;
}>;
}; };
type PreviewType = { type PreviewType = {
url: string; url: string;
title: string; title: string;
image: AttachmentType; image: AttachmentType;
}; };
type QuoteAttachmentType = { type QuoteAttachmentType = {
thumbnail?: AttachmentType; thumbnail?: AttachmentType;
attachmentPointer?: AttachmentPointerClass; attachmentPointer?: AttachmentPointerClass;
}; };
type GroupV2InfoType = {
groupChange?: ArrayBuffer;
masterKey: ArrayBuffer;
revision: number;
members: Array<string>;
};
type GroupV1InfoType = {
id: string;
members: Array<string>;
};
type MessageOptionsType = { type MessageOptionsType = {
attachments?: Array<AttachmentType> | null; attachments?: Array<AttachmentType> | null;
body?: string; body?: string;
expireTimer?: number; expireTimer?: number;
flags?: number; flags?: number;
group?: { group?: {
id: string; id: string;
type: number; type: number;
}; };
groupV2?: GroupV2InfoType;
needsSync?: boolean; needsSync?: boolean;
preview?: Array<PreviewType> | null; preview?: Array<PreviewType> | null;
profileKey?: ArrayBuffer; profileKey?: ArrayBuffer;
quote?: any; quote?: any;
recipients: Array<string>; recipients: Array<string>;
sticker?: any; sticker?: any;
reaction?: any; reaction?: any;
timestamp: number; timestamp: number;
}; };
class Message { class Message {
attachments: Array<any>; attachments: Array<any>;
body?: string; body?: string;
expireTimer?: number; expireTimer?: number;
flags?: number; flags?: number;
group?: { group?: {
id: string; id: string;
type: number; type: number;
}; };
groupV2?: GroupV2InfoType;
needsSync?: boolean; needsSync?: boolean;
preview: any; preview: any;
profileKey?: ArrayBuffer; profileKey?: ArrayBuffer;
quote?: any; quote?: any;
recipients: Array<string>; recipients: Array<string>;
sticker?: any; sticker?: any;
reaction?: any; reaction?: any;
timestamp: number; timestamp: number;
dataMessage: any; dataMessage: any;
attachmentPointers?: Array<any>; attachmentPointers?: Array<any>;
// tslint:disable cyclomatic-complexity // tslint:disable cyclomatic-complexity
constructor(options: MessageOptionsType) { constructor(options: MessageOptionsType) {
this.attachments = options.attachments || []; this.attachments = options.attachments || [];
this.body = options.body; this.body = options.body;
this.expireTimer = options.expireTimer; this.expireTimer = options.expireTimer;
this.flags = options.flags; this.flags = options.flags;
this.group = options.group; this.group = options.group;
this.groupV2 = options.groupV2;
this.needsSync = options.needsSync; this.needsSync = options.needsSync;
this.preview = options.preview; this.preview = options.preview;
this.profileKey = options.profileKey; this.profileKey = options.profileKey;
this.quote = options.quote; this.quote = options.quote;
this.recipients = options.recipients; this.recipients = options.recipients;
this.sticker = options.sticker; this.sticker = options.sticker;
this.reaction = options.reaction; this.reaction = options.reaction;
this.timestamp = options.timestamp; this.timestamp = options.timestamp;
if (!(this.recipients instanceof Array)) { if (!(this.recipients instanceof Array)) {
throw new Error('Invalid recipient list'); throw new Error('Invalid recipient list');
} }
if (!this.group && this.recipients.length !== 1) { if (!this.group && !this.groupV2 && this.recipients.length !== 1) {
throw new Error('Invalid recipient list for non-group'); throw new Error('Invalid recipient list for non-group');
} }
if (typeof this.timestamp !== 'number') { if (typeof this.timestamp !== 'number') {
throw new Error('Invalid timestamp'); throw new Error('Invalid timestamp');
} }
if (this.expireTimer !== undefined && this.expireTimer !== null) { if (this.expireTimer !== undefined && this.expireTimer !== null) {
if (typeof this.expireTimer !== 'number' || !(this.expireTimer >= 0)) { if (typeof this.expireTimer !== 'number' || !(this.expireTimer >= 0)) {
throw new Error('Invalid expireTimer'); throw new Error('Invalid expireTimer');
skipping to change at line 201 skipping to change at line 227
proto.timestamp = this.timestamp; proto.timestamp = this.timestamp;
proto.attachments = this.attachmentPointers; proto.attachments = this.attachmentPointers;
if (this.body) { if (this.body) {
proto.body = this.body; proto.body = this.body;
} }
if (this.flags) { if (this.flags) {
proto.flags = this.flags; proto.flags = this.flags;
} }
if (this.group) { if (this.groupV2) {
proto.groupV2 = new window.textsecure.protobuf.GroupContextV2();
proto.groupV2.masterKey = this.groupV2.masterKey;
proto.groupV2.revision = this.groupV2.revision;
proto.groupV2.groupChange = this.groupV2.groupChange || null;
} else if (this.group) {
proto.group = new window.textsecure.protobuf.GroupContext(); proto.group = new window.textsecure.protobuf.GroupContext();
proto.group.id = stringToArrayBuffer(this.group.id); proto.group.id = stringToArrayBuffer(this.group.id);
proto.group.type = this.group.type; proto.group.type = this.group.type;
} }
if (this.sticker) { if (this.sticker) {
proto.sticker = new window.textsecure.protobuf.DataMessage.Sticker(); proto.sticker = new window.textsecure.protobuf.DataMessage.Sticker();
proto.sticker.packId = hexStringToArrayBuffer(this.sticker.packId); proto.sticker.packId = hexToArrayBuffer(this.sticker.packId);
proto.sticker.packKey = base64ToArrayBuffer(this.sticker.packKey); proto.sticker.packKey = base64ToArrayBuffer(this.sticker.packKey);
proto.sticker.stickerId = this.sticker.stickerId; proto.sticker.stickerId = this.sticker.stickerId;
if (this.sticker.attachmentPointer) { if (this.sticker.attachmentPointer) {
proto.sticker.data = this.sticker.attachmentPointer; proto.sticker.data = this.sticker.attachmentPointer;
} }
} }
if (this.reaction) { if (this.reaction) {
proto.reaction = this.reaction; proto.reaction = this.reaction;
} }
skipping to change at line 305 skipping to change at line 336
_getAttachmentSizeBucket(size: number) { _getAttachmentSizeBucket(size: number) {
return Math.max( return Math.max(
541, 541,
Math.floor(1.05 ** Math.ceil(Math.log(size) / Math.log(1.05))) Math.floor(1.05 ** Math.ceil(Math.log(size) / Math.log(1.05)))
); );
} }
getPaddedAttachment(data: ArrayBuffer) { getPaddedAttachment(data: ArrayBuffer) {
const size = data.byteLength; const size = data.byteLength;
const paddedSize = this._getAttachmentSizeBucket(size); const paddedSize = this._getAttachmentSizeBucket(size);
const padding = window.Signal.Crypto.getZeroes(paddedSize - size); const padding = getZeroes(paddedSize - size);
return window.Signal.Crypto.concatenateBytes(data, padding); return concatenateBytes(data, padding);
} }
async makeAttachmentPointer(attachment: AttachmentType) { async makeAttachmentPointer(attachment: AttachmentType) {
if (typeof attachment !== 'object' || attachment == null) { if (typeof attachment !== 'object' || attachment == null) {
return Promise.resolve(undefined); return Promise.resolve(undefined);
} }
const { data, size } = attachment; const { data, size } = attachment;
if (!(data instanceof ArrayBuffer) && !ArrayBuffer.isView(data)) { if (!(data instanceof ArrayBuffer) && !ArrayBuffer.isView(data)) {
throw new Error( throw new Error(
skipping to change at line 467 skipping to change at line 498
}) })
).catch(error => { ).catch(error => {
if (error instanceof Error && error.name === 'HTTPError') { if (error instanceof Error && error.name === 'HTTPError') {
throw new MessageError(message, error); throw new MessageError(message, error);
} else { } else {
throw error; throw error;
} }
}); });
} }
async sendMessage(attrs: MessageOptionsType, options?: SendOptionsType) { async sendMessage(
attrs: MessageOptionsType,
options?: SendOptionsType
): Promise<CallbackResultType> {
const message = new Message(attrs); const message = new Message(attrs);
const silent = false; const silent = false;
return Promise.all([ return Promise.all([
this.uploadAttachments(message), this.uploadAttachments(message),
this.uploadThumbnails(message), this.uploadThumbnails(message),
this.uploadLinkPreviews(message), this.uploadLinkPreviews(message),
this.uploadSticker(message), this.uploadSticker(message),
]).then( ]).then(
async () => async (): Promise<CallbackResultType> =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
this.sendMessageProto( this.sendMessageProto(
message.timestamp, message.timestamp,
message.recipients || [], message.recipients || [],
message.toProto(), message.toProto(),
(res: CallbackResultType) => { (res: CallbackResultType) => {
res.dataMessage = message.toArrayBuffer(); res.dataMessage = message.toArrayBuffer();
if (res.errors && res.errors.length > 0) { if (res.errors && res.errors.length > 0) {
reject(res); reject(res);
} else { } else {
skipping to change at line 700 skipping to change at line 734
const unauthOptions = { const unauthOptions = {
...options, ...options,
accessKey, accessKey,
}; };
return this.server.getProfileUnauth(number, unauthOptions); return this.server.getProfileUnauth(number, unauthOptions);
} }
return this.server.getProfile(number, options); return this.server.getProfile(number, options);
} }
async getUuidsForE164s(
numbers: Array<string>
): Promise<Dictionary<string | null>> {
return this.server.getUuidsForE164s(numbers);
}
async getAvatar(path: string) { async getAvatar(path: string) {
return this.server.getAvatar(path); return this.server.getAvatar(path);
} }
async getSticker(packId: string, stickerId: string) { async getSticker(packId: string, stickerId: string) {
return this.server.getSticker(packId, stickerId); return this.server.getSticker(packId, stickerId);
} }
async getStickerPackManifest(packId: string) { async getStickerPackManifest(packId: string) {
return this.server.getStickerPackManifest(packId); return this.server.getStickerPackManifest(packId);
} }
skipping to change at line 815 skipping to change at line 855
contentMessage, contentMessage,
Date.now(), Date.now(),
silent, silent,
options options
); );
} }
return Promise.resolve(); return Promise.resolve();
} }
async sendRequestKeySyncMessage(options: SendOptionsType) { async sendFetchManifestSyncMessage(options?: SendOptionsType) {
const myUuid = window.textsecure.storage.user.getUuid();
const myNumber = window.textsecure.storage.user.getNumber();
const myDevice = window.textsecure.storage.user.getDeviceId();
if (myDevice === 1 || myDevice === '1') {
return;
}
const fetchLatest = new window.textsecure.protobuf.SyncMessage.FetchLatest()
;
fetchLatest.type =
window.textsecure.protobuf.SyncMessage.FetchLatest.Type.STORAGE_MANIFEST;
const syncMessage = this.createSyncMessage();
syncMessage.fetchLatest = fetchLatest;
const contentMessage = new window.textsecure.protobuf.Content();
contentMessage.syncMessage = syncMessage;
const silent = true;
await this.sendIndividualProto(
myUuid || myNumber,
contentMessage,
Date.now(),
silent,
options
);
}
async sendRequestKeySyncMessage(options?: SendOptionsType) {
const myUuid = window.textsecure.storage.user.getUuid(); const myUuid = window.textsecure.storage.user.getUuid();
const myNumber = window.textsecure.storage.user.getNumber(); const myNumber = window.textsecure.storage.user.getNumber();
const myDevice = window.textsecure.storage.user.getDeviceId(); const myDevice = window.textsecure.storage.user.getDeviceId();
if (myDevice === 1 || myDevice === '1') { if (myDevice === 1 || myDevice === '1') {
return; return;
} }
const request = new window.textsecure.protobuf.SyncMessage.Request(); const request = new window.textsecure.protobuf.SyncMessage.Request();
request.type = window.textsecure.protobuf.SyncMessage.Request.Type.KEYS; request.type = window.textsecure.protobuf.SyncMessage.Request.Type.KEYS;
skipping to change at line 846 skipping to change at line 914
Date.now(), Date.now(),
silent, silent,
options options
); );
} }
async sendTypingMessage( async sendTypingMessage(
options: { options: {
recipientId: string; recipientId: string;
groupId: string; groupId: string;
groupNumbers: Array<string>; groupMembers: Array<string>;
isTyping: boolean; isTyping: boolean;
timestamp: number; timestamp: number;
}, },
sendOptions: SendOptionsType = {} sendOptions: SendOptionsType = {}
) { ) {
const ACTION_ENUM = window.textsecure.protobuf.TypingMessage.Action; const ACTION_ENUM = window.textsecure.protobuf.TypingMessage.Action;
const { recipientId, groupId, groupNumbers, isTyping, timestamp } = options; const { recipientId, groupId, groupMembers, isTyping, timestamp } = options;
// We don't want to send typing messages to our other devices, but we will // We don't want to send typing messages to our other devices, but we will
// in the group case. // in the group case.
const myNumber = window.textsecure.storage.user.getNumber(); const myNumber = window.textsecure.storage.user.getNumber();
const myUuid = window.textsecure.storage.user.getUuid(); const myUuid = window.textsecure.storage.user.getUuid();
if (recipientId && (myNumber === recipientId || myUuid === recipientId)) { if (recipientId && (myNumber === recipientId || myUuid === recipientId)) {
return null; return null;
} }
if (!recipientId && !groupId) { if (!recipientId && !groupId) {
throw new Error('Need to provide either recipientId or groupId!'); throw new Error('Need to provide either recipientId or groupId!');
} }
const recipients = groupId const recipients = groupId
? (without(groupNumbers, myNumber, myUuid) as Array<string>) ? (without(groupMembers, myNumber, myUuid) as Array<string>)
: [recipientId]; : [recipientId];
const groupIdBuffer = groupId const groupIdBuffer = groupId
? window.Signal.Crypto.fromEncodedBinaryToArrayBuffer(groupId) ? fromEncodedBinaryToArrayBuffer(groupId)
: null; : null;
const action = isTyping ? ACTION_ENUM.STARTED : ACTION_ENUM.STOPPED; const action = isTyping ? ACTION_ENUM.STARTED : ACTION_ENUM.STOPPED;
const finalTimestamp = timestamp || Date.now(); const finalTimestamp = timestamp || Date.now();
const typingMessage = new window.textsecure.protobuf.TypingMessage(); const typingMessage = new window.textsecure.protobuf.TypingMessage();
typingMessage.groupId = groupIdBuffer; typingMessage.groupId = groupIdBuffer;
typingMessage.action = action; typingMessage.action = action;
typingMessage.timestamp = finalTimestamp; typingMessage.timestamp = finalTimestamp;
skipping to change at line 1139 skipping to change at line 1207
const myNumber = window.textsecure.storage.user.getNumber(); const myNumber = window.textsecure.storage.user.getNumber();
const myUuid = window.textsecure.storage.user.getUuid(); const myUuid = window.textsecure.storage.user.getUuid();
const ENUM = const ENUM =
window.textsecure.protobuf.SyncMessage.StickerPackOperation.Type; window.textsecure.protobuf.SyncMessage.StickerPackOperation.Type;
const packOperations = operations.map(item => { const packOperations = operations.map(item => {
const { packId, packKey, installed } = item; const { packId, packKey, installed } = item;
const operation = new window.textsecure.protobuf.SyncMessage.StickerPackOp eration(); const operation = new window.textsecure.protobuf.SyncMessage.StickerPackOp eration();
operation.packId = hexStringToArrayBuffer(packId); operation.packId = hexToArrayBuffer(packId);
operation.packKey = base64ToArrayBuffer(packKey); operation.packKey = base64ToArrayBuffer(packKey);
operation.type = installed ? ENUM.INSTALL : ENUM.REMOVE; operation.type = installed ? ENUM.INSTALL : ENUM.REMOVE;
return operation; return operation;
}); });
const syncMessage = this.createSyncMessage(); const syncMessage = this.createSyncMessage();
syncMessage.stickerPackOperation = packOperations; syncMessage.stickerPackOperation = packOperations;
const contentMessage = new window.textsecure.protobuf.Content(); const contentMessage = new window.textsecure.protobuf.Content();
skipping to change at line 1430 skipping to change at line 1498
[], [],
[], [],
false, false,
options options
).catch(logError('resetSession/sendSync error:')); ).catch(logError('resetSession/sendSync error:'));
return Promise.all([sendToContactPromise, sendSyncPromise]); return Promise.all([sendToContactPromise, sendSyncPromise]);
} }
async sendMessageToGroup( async sendMessageToGroup(
groupId: string, {
recipients: Array<string>, attachments,
messageText: string, expireTimer,
attachments: Array<AttachmentType>, groupV2,
quote: any, groupV1,
preview: any, messageText,
sticker: any, preview,
reaction: any, profileKey,
timestamp: number, quote,
expireTimer: number | undefined, reaction,
profileKey?: ArrayBuffer, sticker,
timestamp,
}: {
attachments?: Array<AttachmentType>;
expireTimer?: number;
groupV2?: GroupV2InfoType;
groupV1?: GroupV1InfoType;
messageText?: string;
preview?: any;
profileKey?: ArrayBuffer;
quote?: any;
reaction?: any;
sticker?: any;
timestamp: number;
},
options?: SendOptionsType options?: SendOptionsType
) { ): Promise<CallbackResultType> {
if (!groupV1 && !groupV2) {
throw new Error(
'sendMessageToGroup: Neither group1 nor groupv2 information provided!'
);
}
const myE164 = window.textsecure.storage.user.getNumber(); const myE164 = window.textsecure.storage.user.getNumber();
const myUuid = window.textsecure.storage.user.getNumber(); const myUuid = window.textsecure.storage.user.getNumber();
// prettier-ignore
const recipients = groupV2
? groupV2.members
: groupV1
? groupV1.members
: [];
const attrs = { const attrs = {
recipients: recipients.filter(r => r !== myE164 && r !== myUuid), recipients: recipients.filter(r => r !== myE164 && r !== myUuid),
body: messageText, body: messageText,
timestamp, timestamp,
attachments, attachments,
quote, quote,
preview, preview,
sticker, sticker,
reaction, reaction,
expireTimer, expireTimer,
profileKey, profileKey,
group: { groupV2,
id: groupId, group: groupV1
type: window.textsecure.protobuf.GroupContext.Type.DELIVER, ? {
}, id: groupV1.id,
type: window.textsecure.protobuf.GroupContext.Type.DELIVER,
}
: undefined,
}; };
if (recipients.length === 0) { if (recipients.length === 0) {
return Promise.resolve({ return Promise.resolve({
successfulIdentifiers: [], successfulIdentifiers: [],
failoverIdentifiers: [], failoverIdentifiers: [],
errors: [], errors: [],
unidentifiedDeliveries: [], unidentifiedDeliveries: [],
dataMessage: await this.getMessageProtoObj(attrs), dataMessage: await this.getMessageProtoObj(attrs),
discoveredIdentifierPairs: [],
}); });
} }
return this.sendMessage(attrs, options); return this.sendMessage(attrs, options);
} }
async createGroup( async getGroup(options: GroupCredentialsType): Promise<GroupClass> {
targetIdentifiers: Array<string>, return this.server.getGroup(options);
id: string,
name: string,
avatar: AttachmentType,
options?: SendOptionsType
) {
const proto = new window.textsecure.protobuf.DataMessage();
proto.group = new window.textsecure.protobuf.GroupContext();
proto.group.id = stringToArrayBuffer(id);
proto.group.type = window.textsecure.protobuf.GroupContext.Type.UPDATE;
proto.group.membersE164 = targetIdentifiers;
proto.group.name = name;
return this.makeAttachmentPointer(avatar).then(async attachment => {
if (!proto.group) {
throw new Error('createGroup: proto.group was set to null');
}
proto.group.avatar = attachment;
return this.sendGroupProto(
targetIdentifiers,
proto,
Date.now(),
options
).then(() => {
if (!proto.group) {
throw new Error('createGroup: proto.group was set to null');
}
return proto.group.id;
});
});
} }
async getGroupLog(
async updateGroup( startVersion: number,
groupId: string, options: GroupCredentialsType
name: string, ): Promise<GroupLogResponseType> {
avatar: AttachmentType, return this.server.getGroupLog(startVersion, options);
targetIdentifiers: Array<string>, }
options?: SendOptionsType async getGroupAvatar(key: string): Promise<ArrayBuffer> {
) { return this.server.getGroupAvatar(key);
const proto = new window.textsecure.protobuf.DataMessage(); }
proto.group = new window.textsecure.protobuf.GroupContext(); async modifyGroup(
changes: GroupChangeClass.Actions,
proto.group.id = stringToArrayBuffer(groupId); options: GroupCredentialsType
proto.group.type = window.textsecure.protobuf.GroupContext.Type.UPDATE; ): Promise<GroupChangeClass> {
proto.group.name = name; return this.server.modifyGroup(changes, options);
proto.group.membersE164 = targetIdentifiers;
return this.makeAttachmentPointer(avatar).then(async attachment => {
if (!proto.group) {
throw new Error('updateGroup: proto.group was set to null');
}
proto.group.avatar = attachment;
return this.sendGroupProto(
targetIdentifiers,
proto,
Date.now(),
options
).then(() => {
if (!proto.group) {
throw new Error('updateGroup: proto.group was set to null');
}
return proto.group.id;
});
});
} }
async addIdentifierToGroup(
groupId: string,
newIdentifiers: Array<string>,
options: SendOptionsType
) {
const proto = new window.textsecure.protobuf.DataMessage();
proto.group = new window.textsecure.protobuf.GroupContext();
proto.group.id = stringToArrayBuffer(groupId);
proto.group.type = window.textsecure.protobuf.GroupContext.Type.UPDATE;
proto.group.membersE164 = newIdentifiers;
return this.sendGroupProto(newIdentifiers, proto, Date.now(), options);
}
async setGroupName(
groupId: string,
name: string,
groupIdentifiers: Array<string>,
options: SendOptionsType
) {
const proto = new window.textsecure.protobuf.DataMessage();
proto.group = new window.textsecure.protobuf.GroupContext();
proto.group.id = stringToArrayBuffer(groupId);
proto.group.type = window.textsecure.protobuf.GroupContext.Type.UPDATE;
proto.group.name = name;
proto.group.membersE164 = groupIdentifiers;
return this.sendGroupProto(groupIdentifiers, proto, Date.now(), options);
}
async setGroupAvatar(
groupId: string,
avatar: AttachmentType,
groupIdentifiers: Array<string>,
options: SendOptionsType
) {
const proto = new window.textsecure.protobuf.DataMessage();
proto.group = new window.textsecure.protobuf.GroupContext();
proto.group.id = stringToArrayBuffer(groupId);
proto.group.type = window.textsecure.protobuf.GroupContext.Type.UPDATE;
proto.group.membersE164 = groupIdentifiers;
return this.makeAttachmentPointer(avatar).then(async attachment => {
if (!proto.group) {
throw new Error('setGroupAvatar: proto.group was set to null');
}
proto.group.avatar = attachment;
return this.sendGroupProto(groupIdentifiers, proto, Date.now(), options);
});
}
async leaveGroup(
groupId: string,
groupIdentifiers: Array<string>,
options?: SendOptionsType
) {
const proto = new window.textsecure.protobuf.DataMessage();
proto.group = new window.textsecure.protobuf.GroupContext();
proto.group.id = stringToArrayBuffer(groupId);
proto.group.type = window.textsecure.protobuf.GroupContext.Type.QUIT;
return this.sendGroupProto(groupIdentifiers, proto, Date.now(), options);
}
async sendExpirationTimerUpdateToGroup( async sendExpirationTimerUpdateToGroup(
groupId: string, groupId: string,
groupIdentifiers: Array<string>, groupIdentifiers: Array<string>,
expireTimer: number | undefined, expireTimer: number | undefined,
timestamp: number, timestamp: number,
profileKey?: ArrayBuffer, profileKey?: ArrayBuffer,
options?: SendOptionsType options?: SendOptionsType
) { ): Promise<CallbackResultType> {
const myNumber = window.textsecure.storage.user.getNumber(); const myNumber = window.textsecure.storage.user.getNumber();
const myUuid = window.textsecure.storage.user.getUuid(); const myUuid = window.textsecure.storage.user.getUuid();
const recipients = groupIdentifiers.filter( const recipients = groupIdentifiers.filter(
identifier => identifier !== myNumber && identifier !== myUuid identifier => identifier !== myNumber && identifier !== myUuid
); );
const attrs = { const attrs = {
recipients, recipients,
timestamp, timestamp,
expireTimer, expireTimer,
profileKey, profileKey,
skipping to change at line 1640 skipping to change at line 1626
}, },
}; };
if (recipients.length === 0) { if (recipients.length === 0) {
return Promise.resolve({ return Promise.resolve({
successfulIdentifiers: [], successfulIdentifiers: [],
failoverIdentifiers: [], failoverIdentifiers: [],
errors: [], errors: [],
unidentifiedDeliveries: [], unidentifiedDeliveries: [],
dataMessage: await this.getMessageProtoObj(attrs), dataMessage: await this.getMessageProtoObj(attrs),
discoveredIdentifierPairs: [],
}); });
} }
return this.sendMessage(attrs, options); return this.sendMessage(attrs, options);
} }
async sendExpirationTimerUpdateToIdentifier( async sendExpirationTimerUpdateToIdentifier(
identifier: string, identifier: string,
expireTimer: number | undefined, expireTimer: number | undefined,
timestamp: number, timestamp: number,
profileKey?: ArrayBuffer, profileKey?: ArrayBuffer,
options?: SendOptionsType options?: SendOptionsType
) { ) {
return this.sendMessage( return this.sendMessage(
{ {
recipients: [identifier], recipients: [identifier],
skipping to change at line 1684 skipping to change at line 1672
): Promise<ArrayBuffer> { ): Promise<ArrayBuffer> {
return this.server.getStorageManifest(options); return this.server.getStorageManifest(options);
} }
async getStorageRecords( async getStorageRecords(
data: ArrayBuffer, data: ArrayBuffer,
options: StorageServiceCallOptionsType options: StorageServiceCallOptionsType
): Promise<ArrayBuffer> { ): Promise<ArrayBuffer> {
return this.server.getStorageRecords(data, options); return this.server.getStorageRecords(data, options);
} }
async modifyStorageRecords(
data: ArrayBuffer,
options: StorageServiceCallOptionsType
): Promise<ArrayBuffer> {
return this.server.modifyStorageRecords(data, options);
}
} }
 End of changes. 36 change blocks. 
167 lines changed or deleted 163 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)