add userblocking opengroupv2 and quoting back of messages

pull/1576/head
Audric Ackermann 3 years ago
parent 5916ce5cbe
commit 98b69c17f0
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -6,8 +6,16 @@
"defaultPoWDifficulty": "1",
"seedNodeList": [
{
"url": "http://public.loki.foundation:38157/",
"ip_url": "http://144.76.164.202:38157/"
"ip_url": "http://116.203.53.213:4433/",
"url": "https://storage.seed1.loki.network:4433/"
},
{
"ip_url": "http://212.199.114.66:4433/",
"url": "https://storage.seed3.loki.network:4433/"
},
{
"ip_url": "http://144.76.164.202:4433/",
"url": "https://public.loki.foundation:4433/"
}
],
"updatesEnabled": false,

@ -66,8 +66,7 @@
};
// don't wait for this to finish
// FIXME audric
// checkForUpgrades();
checkForUpgrades();
window.extension = window.extension || {};

@ -49,14 +49,10 @@ window.getHostName = () => config.hostname;
window.getServerTrustRoot = () => config.serverTrustRoot;
window.JobQueue = JobQueue;
window.isBehindProxy = () => Boolean(config.proxyUrl);
// FIXME audric
window.getStoragePubKey = key => key.substring(0, key.length - 2);
// window.isDev() ? key.substring(0, key.length - 2) : key;
window.getStoragePubKey = key => (window.isDev() ? key.substring(0, key.length - 2) : key);
// FIXME audric
// config.defaultFileServer
window.getDefaultFileServer = () => 'https://file-dev.getsession.org';
window.getDefaultFileServer = () => config.defaultFileServer;
window.initialisedAPI = false;
window.lokiFeatureFlags = {

@ -38,7 +38,9 @@ export class RemoveModeratorsDialog extends React.Component<Props, State> {
}
public async componentDidMount() {
this.channelAPI = await this.props.convo.getPublicSendData();
if (this.props.convo.isOpenGroupV1()) {
this.channelAPI = await this.props.convo.getPublicSendData();
}
void this.refreshModList();
}
@ -133,8 +135,13 @@ export class RemoveModeratorsDialog extends React.Component<Props, State> {
}
private async refreshModList() {
// get current list of moderators
const modPubKeys = (await this.channelAPI.getModerators()) as Array<string>;
let modPubKeys: Array<string> = [];
if (this.props.convo.isOpenGroupV1()) {
// get current list of moderators
modPubKeys = (await this.channelAPI.getModerators()) as Array<string>;
} else if (this.props.convo.isOpenGroupV2()) {
modPubKeys = this.props.convo.getGroupAdmins() || [];
}
const convos = ConversationController.getInstance().getConversations();
const moderatorsConvos = modPubKeys
.map(
@ -186,7 +193,13 @@ export class RemoveModeratorsDialog extends React.Component<Props, State> {
this.setState({
removingInProgress: true,
});
const res = await this.channelAPI.serverAPI.removeModerators(removedMods);
let res;
if (this.props.convo.isOpenGroupV1()) {
res = await this.channelAPI.serverAPI.removeModerators(removedMods);
} else if (this.props.convo.isOpenGroupV2()) {
// FIXME audric removeModerators opengroupv2
throw new Error('removeModerators opengroupv2 TODO');
}
if (!res) {
window.log.warn('failed to remove moderators:', res);

@ -440,6 +440,7 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
'connectToServerSuccess',
window.i18n('connectToServerSuccess')
);
return true;
} else {
ToastUtils.pushToastError('connectToServerFail', window.i18n('connectToServerFail'));
}
@ -449,6 +450,7 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
} finally {
this.setState({ loading: false });
}
return false;
}
private async handleJoinChannelButtonClick(serverUrl: string) {
@ -460,7 +462,10 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
// guess if this is an open
if (serverUrl.match(openGroupV2CompleteURLRegex)) {
await this.handleOpenGroupJoinV2(serverUrl);
const groupCreated = await this.handleOpenGroupJoinV2(serverUrl);
if (groupCreated) {
this.handleToggleOverlay(undefined);
}
} else {
// this is an open group v1
await this.handleOpenGroupJoinV1(serverUrl);

@ -588,7 +588,7 @@ export class SessionCompositionBox extends React.Component<Props, State> {
private renderQuotedMessage() {
const { quotedMessageProps, removeQuotedMessage } = this.props;
if (quotedMessageProps && quotedMessageProps.id) {
if (quotedMessageProps?.id) {
return (
<SessionQuotedMessageComposition
quotedMessageProps={quotedMessageProps}

@ -562,21 +562,16 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
return [];
}
public async makeQuote(quotedMessage: any) {
const { getName } = window.Signal.Types.Contact;
const contact = quotedMessage.getContact();
public async makeQuote(quotedMessage: MessageModel) {
const attachments = quotedMessage.get('attachments');
const preview = quotedMessage.get('preview');
const body = quotedMessage.get('body');
const embeddedContact = quotedMessage.get('contact');
const embeddedContactName =
embeddedContact && embeddedContact.length > 0 ? getName(embeddedContact[0]) : '';
const quotedAttachments = await this.getQuoteAttachment(attachments, preview);
return {
author: contact.id,
author: quotedMessage.getSource(),
id: quotedMessage.get('sent_at'),
text: body || embeddedContactName,
text: body,
attachments: quotedAttachments,
};
}
@ -756,10 +751,10 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
serverTimestamp: this.isPublic() ? new Date().getTime() : undefined,
};
const model = await this.addSingleMessage(attributes);
const messageModel = await this.addSingleMessage(attributes);
this.set({
lastMessage: model.getNotificationText(),
lastMessage: messageModel.getNotificationText(),
lastMessageStatus: 'sending',
active_at: now,
});
@ -770,11 +765,11 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
const error = new Error('Network is not available');
error.name = 'SendMessageNetworkError';
(error as any).number = this.id;
await model.saveErrors([error]);
await messageModel.saveErrors([error]);
return null;
}
this.queueJob(async () => {
await this.sendMessageJob(model, expireTimer);
await this.sendMessageJob(messageModel, expireTimer);
});
return null;
}
@ -1220,13 +1215,13 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
}
// Not sure if we care about updating the database
}
public async setGroupNameAndAvatar(name: any, avatarPath: any) {
public async setGroupNameAndAvatar(name: string, avatarPath: string) {
const currentName = this.get('name');
const profileAvatar = this.get('profileAvatar');
const profileAvatar = this.get('avatar');
if (profileAvatar !== avatarPath || currentName !== name) {
// only update changed items
if (profileAvatar !== avatarPath) {
this.set({ profileAvatar: avatarPath });
this.set({ avatar: avatarPath });
}
if (currentName !== name) {
this.set({ name });
@ -1236,9 +1231,9 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
}
}
public async setProfileAvatar(avatar: any) {
const profileAvatar = this.get('profileAvatar');
const profileAvatar = this.get('avatar');
if (profileAvatar !== avatar) {
this.set({ profileAvatar: avatar });
this.set({ avatar });
await this.commit();
}
}

@ -761,7 +761,7 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
// NOTE: we want to go for the v1 if this is an OpenGroupV1 or not an open group at all
// because there is a fallback invoked on uploadV1() for attachments for not open groups attachments
const openGroupV1 = conversation?.toOpenGroupV1();
const openGroupV1 = conversation?.isOpenGroupV1() ? conversation?.toOpenGroupV1() : undefined;
attachmentPromise = AttachmentUtils.uploadAttachmentsV1(
filenameOverridenAttachments,
openGroupV1

@ -3,6 +3,7 @@ import { ConversationController } from '../../session/conversations';
import { PromiseUtils } from '../../session/utils';
import { allowOnlyOneAtATime } from '../../session/utils/Promise';
import { forceSyncConfigurationNowIfNeeded } from '../../session/utils/syncUtils';
import { arrayBufferFromFile } from '../../types/Attachment';
import { openGroupPrefix, prefixify } from '../utils/OpenGroupUtils';
interface OpenGroupParams {
@ -11,6 +12,70 @@ interface OpenGroupParams {
conversationId: string;
}
export async function updateOpenGroupV1(convo: any, groupName: string, avatar: any) {
const API = await convo.getPublicSendData();
if (avatar) {
// I hate duplicating this...
const readFile = async (attachment: any) =>
new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.onload = (e: any) => {
const data = e.target.result;
resolve({
...attachment,
data,
size: data.byteLength,
});
};
fileReader.onerror = reject;
fileReader.onabort = reject;
fileReader.readAsArrayBuffer(attachment.file);
});
const avatarAttachment: any = await readFile({ file: avatar });
// We want a square for iOS
const withBlob = await window.Signal.Util.AttachmentUtil.autoScale(
{
contentType: avatar.type,
file: new Blob([avatarAttachment.data], {
type: avatar.contentType,
}),
},
{
maxSide: 640,
maxSize: 1000 * 1024,
}
);
const dataResized = await arrayBufferFromFile(withBlob.file);
// const tempUrl = window.URL.createObjectURL(avatar);
// Get file onto public chat server
const fileObj = await API.serverAPI.putAttachment(dataResized);
if (fileObj === null) {
// problem
window.log.warn('File upload failed');
return;
}
// lets not allow ANY URLs, lets force it to be local to public chat server
const url = new URL(fileObj.url);
// write it to the channel
await API.setChannelAvatar(url.pathname);
}
if (await API.setChannelName(groupName)) {
// queue update from server
// and let that set the conversation
API.pollForChannelOnce();
// or we could just directly call
// convo.setGroupName(groupName);
// but gut is saying let the server be the definitive storage of the state
// and trickle down from there
}
}
export class OpenGroup {
private static readonly serverRegex = new RegExp(
'^((https?:\\/\\/){0,1})([\\w-]{2,}\\.){1,2}[\\w-]{2,}$'

@ -58,30 +58,6 @@ export const buildUrl = (request: OpenGroupV2Request): URL | null => {
}
};
/**
* Map of serverUrl to roomId to list of moderators as a Set
*/
export const cachedModerators: Map<string, Map<string, Set<string>>> = new Map();
export const setCachedModerators = (
serverUrl: string,
roomId: string,
newModerators: Array<string>
) => {
let allRoomsMods = cachedModerators.get(serverUrl);
if (!allRoomsMods) {
cachedModerators.set(serverUrl, new Map());
allRoomsMods = cachedModerators.get(serverUrl);
}
// tslint:disable: no-non-null-assertion
if (!allRoomsMods!.get(roomId)) {
allRoomsMods!.set(roomId, new Set());
}
newModerators.forEach(m => {
allRoomsMods!.get(roomId)?.add(m);
});
};
export const parseMessages = async (
rawMessages: Array<Record<string, any>>
): Promise<Array<OpenGroupMessageV2>> => {

@ -10,23 +10,16 @@ import {
toHex,
} from '../../session/utils/String';
import { getIdentityKeyPair, getOurPubKeyStrFromCache } from '../../session/utils/User';
import {
getCompleteEndpointUrl,
getCompleteUrlFromRoom,
getOpenGroupV2ConversationId,
} from '../utils/OpenGroupUtils';
import { getCompleteEndpointUrl, getOpenGroupV2ConversationId } from '../utils/OpenGroupUtils';
import {
buildUrl,
cachedModerators,
OpenGroupRequestCommonType,
OpenGroupV2Info,
OpenGroupV2Request,
parseMessages,
setCachedModerators,
} from './ApiUtil';
import {
parseMemberCount,
parseModerators,
parseRooms,
parseStatusCodeFromOnionRequest,
} from './OpenGroupAPIV2Parser';
@ -373,47 +366,6 @@ export const postMessage = async (
return OpenGroupMessageV2.fromJson(rawMessage);
};
/** Those functions are related to moderators management */
// export const getModerators = async ({
// serverUrl,
// roomId,
// }: OpenGroupRequestCommonType): Promise<Array<string>> => {
// const request: OpenGroupV2Request = {
// method: 'GET',
// room: roomId,
// server: serverUrl,
// isAuthRequired: true,
// endpoint: 'moderators',
// };
// const result = await sendOpenGroupV2Request(request);
// const statusCode = parseStatusCodeFromOnionRequest(result);
// if (statusCode !== 200) {
// window.log.error(`Could not getModerators, status code: ${statusCode}`);
// return [];
// }
// const moderators = parseModerators(result);
// if (moderators === undefined) {
// // if moderators is undefined, do not update t+++++++++++++++++++++++++he cached moderator list
// window.log.warn('Could not getModerators, got no moderatorsGot at all in json.');
// return [];
// }
// setCachedModerators(serverUrl, roomId, moderators || []);
// return moderators || [];
// };
export const isUserModerator = (
publicKey: string,
roomInfos: OpenGroupRequestCommonType
): boolean => {
return (
cachedModerators
?.get(roomInfos.serverUrl)
?.get(roomInfos.roomId)
?.has(publicKey) || false
);
};
export const banUser = async (
userToBan: PubKey,
roomInfos: OpenGroupRequestCommonType
@ -534,6 +486,33 @@ export const downloadFileOpenGroupV2 = async (
return new Uint8Array(fromBase64ToArrayBuffer(base64Data));
};
export const downloadFileOpenGroupV2ByUrl = async (
pathName: string,
roomInfos: OpenGroupRequestCommonType
): Promise<Uint8Array | null> => {
const request: OpenGroupV2Request = {
method: 'GET',
room: roomInfos.roomId,
server: roomInfos.serverUrl,
isAuthRequired: false,
endpoint: pathName,
};
const result = await sendOpenGroupV2Request(request);
const statusCode = parseStatusCodeFromOnionRequest(result);
if (statusCode !== 200) {
return null;
}
// we should probably change the logic of sendOnionRequest to not have all those levels
const base64Data = (result as any)?.result?.result as string | undefined;
if (!base64Data) {
return null;
}
return new Uint8Array(fromBase64ToArrayBuffer(base64Data));
};
export const downloadPreviewOpenGroupV2 = async (
roomInfos: OpenGroupRequestCommonType
): Promise<Uint8Array | null> => {
@ -595,9 +574,42 @@ export const uploadFileOpenGroupV2 = async (
if (!fileId) {
return null;
}
const fileUrl = getCompleteEndpointUrl(roomInfos, `${filesEndpoint}/${fileId}`);
const fileUrl = getCompleteEndpointUrl(roomInfos, `${filesEndpoint}/${fileId}`, false);
return {
fileId: fileId,
fileUrl,
};
};
export const uploadImageForRoomOpenGroupV2 = async (
fileContent: Uint8Array,
roomInfos: OpenGroupRequestCommonType
): Promise<{ fileUrl: string } | null> => {
if (!fileContent || !fileContent.length) {
return null;
}
const queryParams = {
file: fromArrayBufferToBase64(fileContent),
};
const imageEndpoint = `rooms/${roomInfos.roomId}/image`;
const request: OpenGroupV2Request = {
method: 'POST',
room: roomInfos.roomId,
server: roomInfos.serverUrl,
isAuthRequired: true,
endpoint: imageEndpoint,
queryParams,
};
const result = await sendOpenGroupV2Request(request);
const statusCode = parseStatusCodeFromOnionRequest(result);
if (statusCode !== 200) {
return null;
}
const fileUrl = getCompleteEndpointUrl(roomInfos, `${imageEndpoint}`, true);
return {
fileUrl,
};
};

@ -1,10 +1,5 @@
import { getV2OpenGroupRoomByRoomId, saveV2OpenGroupRoom } from '../../data/opengroups';
import {
OpenGroupRequestCommonType,
OpenGroupV2CompactPollRequest,
parseMessages,
setCachedModerators,
} from './ApiUtil';
import { OpenGroupV2CompactPollRequest, parseMessages } from './ApiUtil';
import { parseStatusCodeFromOnionRequest } from './OpenGroupAPIV2Parser';
import _ from 'lodash';
import { sendViaOnion } from '../../session/onions/onionSend';
@ -201,7 +196,6 @@ const parseCompactPollResult = async (
const moderators = rawMods.sort() as Array<string>;
const deletions = rawDeletions as Array<number>;
const statusCode = rawStatusCode as number;
setCachedModerators(serverUrl, room_id, moderators || []);
return {
roomId: room_id,

@ -10,7 +10,7 @@ import { getV2OpenGroupRoom, saveV2OpenGroupRoom } from '../../data/opengroups';
import { OpenGroupMessageV2 } from './OpenGroupMessageV2';
import { handleOpenGroupV2Message } from '../../receiver/receiver';
const pollForEverythingInterval = 6 * 1000;
const pollForEverythingInterval = 4 * 1000;
/**
* An OpenGroupServerPollerV2 polls for everything for a particular server. We should
@ -152,7 +152,7 @@ export class OpenGroupServerPoller {
compactFetchResults = compactFetchResults.filter(result =>
this.roomIdsToPoll.has(result.roomId)
);
window.log.warn(`compactFetchResults for ${this.serverUrl}:`, compactFetchResults);
// window.log.debug(`compactFetchResults for ${this.serverUrl}:`, compactFetchResults);
// ==> At this point all those results need to trigger conversation updates, so update what we have to update
await handleCompactPollResults(this.serverUrl, compactFetchResults);

@ -0,0 +1,83 @@
import { ApiV2 } from '.';
import { getV2OpenGroupRoom } from '../../data/opengroups';
import { ConversationModel } from '../../models/conversation';
import { downloadAttachmentOpenGroupV2 } from '../../receiver/attachments';
import { arrayBufferFromFile } from '../../types/Attachment';
import { AttachmentUtil } from '../../util';
export async function updateOpenGroupV2(convo: ConversationModel, groupName: string, avatar: any) {
if (avatar) {
// I hate duplicating this...
const readFile = async (attachment: any) =>
new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.onload = (e: any) => {
const data = e.target.result;
resolve({
...attachment,
data,
size: data.byteLength,
});
};
fileReader.onerror = reject;
fileReader.onabort = reject;
fileReader.readAsArrayBuffer(attachment.file);
});
const avatarAttachment: any = await readFile({ file: avatar });
// We want a square
const withBlob = await AttachmentUtil.autoScale(
{
contentType: avatar.type,
file: new Blob([avatarAttachment.data], {
type: avatar.contentType,
}),
},
{
maxSide: 640,
maxSize: 1000 * 1024,
}
);
const dataResized = await arrayBufferFromFile(withBlob.file);
const roomInfos = await getV2OpenGroupRoom(convo.id);
if (!roomInfos || !dataResized.byteLength) {
return false;
}
const uploadedFileDetails = await ApiV2.uploadImageForRoomOpenGroupV2(
new Uint8Array(dataResized),
roomInfos
);
if (!uploadedFileDetails || !uploadedFileDetails.fileUrl) {
window.log.warn('File opengroupv2 upload failed');
return;
}
let url: URL;
try {
url = new URL(uploadedFileDetails.fileUrl);
const pathname = url.pathname;
const downloaded = await downloadAttachmentOpenGroupV2(pathname, roomInfos);
if (!(downloaded instanceof Uint8Array)) {
const typeFound = typeof downloaded;
throw new Error(`Expected a plain Uint8Array but got ${typeFound}`);
}
const upgraded = await window.Signal.Migrations.processNewAttachment({
data: downloaded.buffer,
isRaw: true,
url: pathname,
});
// TODO on our opengroupv2 we don't have a way to know when the file changed on the server.
// maybe we should download it once in a while even if we don't know if the file changed?
convo.set('avatarPointer', pathname);
window.log.warn('TODO update of roomName');
await convo.setGroupNameAndAvatar(convo.get('name') || 'Unknown', upgraded.path);
} catch (e) {
window.log.error(`Could not decrypt profile image: ${e}`);
}
}
return undefined;
}

@ -61,10 +61,21 @@ export function getCompleteUrlFromRoom(roomInfos: OpenGroupV2Room) {
/**
* This function returns a base url to this room
* This is basically used for building url after posting an attachment
* hasRoomInEndpoint = true means the roomId is already in the endpoint.
* so we don't add the room after the serverUrl.
*
*/
export function getCompleteEndpointUrl(roomInfos: OpenGroupRequestCommonType, endpoint: string) {
export function getCompleteEndpointUrl(
roomInfos: OpenGroupRequestCommonType,
endpoint: string,
hasRoomInEndpoint: boolean
) {
// serverUrl has the port and protocol already
return `${roomInfos.serverUrl}/${roomInfos.roomId}/${endpoint}`;
if (!hasRoomInEndpoint) {
return `${roomInfos.serverUrl}/${roomInfos.roomId}/${endpoint}`;
}
// not room based, the endpoint already has the room in it
return `${roomInfos.serverUrl}/${endpoint}`;
}
/**

@ -5,7 +5,10 @@ import { saveMessage } from '../../ts/data/data';
import { fromBase64ToArrayBuffer } from '../session/utils/String';
import { AttachmentDownloads, AttachmentUtils } from '../session/utils';
import { ConversationModel } from '../models/conversation';
import { downloadFileOpenGroupV2 } from '../opengroup/opengroupV2/OpenGroupAPIV2';
import {
downloadFileOpenGroupV2,
downloadFileOpenGroupV2ByUrl,
} from '../opengroup/opengroupV2/OpenGroupAPIV2';
import { OpenGroupRequestCommonType } from '../opengroup/opengroupV2/ApiUtil';
export async function downloadAttachment(attachment: any) {
@ -85,10 +88,29 @@ export async function downloadAttachment(attachment: any) {
};
}
/**
*
* @param attachment Either the details of the attachment to download (on a per room basis), or the pathName to the file you want to get
*/
export async function downloadAttachmentOpenGroupV2(
attachment: any,
attachment:
| {
id: number;
url: string;
size: number;
}
| string,
roomInfos: OpenGroupRequestCommonType
) {
if (typeof attachment === 'string') {
const dataUintFromUrl = await downloadFileOpenGroupV2ByUrl(attachment, roomInfos);
if (!dataUintFromUrl?.length) {
window.log.error('Failed to download attachment. Length is 0');
throw new Error(`Failed to download attachment. Length is 0 for ${attachment}`);
}
return dataUintFromUrl;
}
const dataUint = await downloadFileOpenGroupV2(attachment.id, roomInfos);
if (!dataUint?.length) {
@ -115,7 +137,7 @@ export async function downloadAttachmentOpenGroupV2(
return {
..._.omit(attachment, 'digest', 'key'),
data,
data: data.buffer,
};
}

@ -29,7 +29,6 @@ export async function updateProfile(
newProfile.displayName = profile.displayName;
// TODO: may need to allow users to reset their avatars to null
if (profile.profilePicture) {
const prevPointer = conversation.get('avatarPointer');
const needsUpdate = !prevPointer || !_.isEqual(prevPointer, profile.profilePicture);
@ -319,7 +318,7 @@ export async function handleDataMessage(
message,
};
await handleMessageEvent(ev);
await handleMessageEvent(ev); // dataMessage
}
type MessageDuplicateSearchType = {

@ -1,63 +0,0 @@
export async function updateOpenGroup(convo: any, groupName: string, avatar: any) {
const API = await convo.getPublicSendData();
if (avatar) {
// I hate duplicating this...
const readFile = async (attachment: any) =>
new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.onload = (e: any) => {
const data = e.target.result;
resolve({
...attachment,
data,
size: data.byteLength,
});
};
fileReader.onerror = reject;
fileReader.onabort = reject;
fileReader.readAsArrayBuffer(attachment.file);
});
const avatarAttachment: any = await readFile({ file: avatar });
// We want a square for iOS
const withBlob = await window.Signal.Util.AttachmentUtil.autoScale(
{
contentType: avatar.type,
file: new Blob([avatarAttachment.data], {
type: avatar.contentType,
}),
},
{
maxSide: 640,
maxSize: 1000 * 1024,
}
);
const dataResized = await window.Signal.Types.Attachment.arrayBufferFromFile(withBlob.file);
// const tempUrl = window.URL.createObjectURL(avatar);
// Get file onto public chat server
const fileObj = await API.serverAPI.putAttachment(dataResized);
if (fileObj === null) {
// problem
window.log.warn('File upload failed');
return;
}
// lets not allow ANY URLs, lets force it to be local to public chat server
const url = new URL(fileObj.url);
// write it to the channel
await API.setChannelAvatar(url.pathname);
}
if (await API.setChannelName(groupName)) {
// queue update from server
// and let that set the conversation
API.pollForChannelOnce();
// or we could just directly call
// convo.setGroupName(groupName);
// but gut is saying let the server be the definitive storage of the state
// and trickle down from there
}
}

@ -2,7 +2,7 @@ import { queueAttachmentDownloads } from './attachments';
import { Quote } from './types';
import { PubKey } from '../session/types';
import _ from 'lodash';
import _, { toNumber } from 'lodash';
import { SignalService } from '../protobuf';
import { StringUtils, UserUtils } from '../session/utils';
import { ConversationController } from '../session/conversations';
@ -12,6 +12,7 @@ import { MessageController } from '../session/messages';
import { getMessageById, getMessagesBySentAt } from '../../ts/data/data';
import { actions as conversationActions } from '../state/ducks/conversations';
import { updateProfile } from './dataMessage';
import Long from 'long';
async function handleGroups(
conversation: ConversationModel,
@ -95,14 +96,18 @@ async function copyFromQuotedMessage(
return;
}
const { attachments, id, author } = quote;
const { attachments, id: longId, author } = quote;
const firstAttachment = attachments[0];
const collection = await getMessagesBySentAt(id);
const found = collection.find((item: any) => {
const messageAuthor = item.getContact();
const id: number = Long.isLong(longId) ? longId.toNumber() : longId;
// We always look for the quote by sentAt timestamp, for opengroups, closed groups and session chats
// this will return an array of sent message by id we have locally.
return messageAuthor && author === messageAuthor.id;
const collection = await getMessagesBySentAt(id);
// we now must make sure this is the sender we expect
const found = collection.find(message => {
return Boolean(author === message.getSource());
});
if (!found) {

@ -335,6 +335,7 @@ export async function handleOpenGroupV2Message(
return;
}
const isMe = UserUtils.isUsFromCache(sender);
// for an opengroupv2 incoming message the serverTimestamp and the timestamp
const messageCreationData: MessageCreationData = {
isPublic: true,
sourceDevice: 1,

@ -1,8 +1,8 @@
import { SignalService } from '../protobuf';
export interface Quote {
id: any;
author: any;
id: number; // this is in fact a uint64 so we will have an issue
author: string;
attachments: Array<any>;
text: string;
referencedMessageNotFound: boolean;

@ -5,7 +5,6 @@ import _ from 'lodash';
import { fromHex, fromHexToArray, toHex } from '../utils/String';
import { BlockedNumberController } from '../../util/blockedNumberController';
import { ConversationController } from '../conversations';
import { updateOpenGroup } from '../../receiver/openGroups';
import {
addClosedGroupEncryptionKeyPair,
getIdentityKeyById,
@ -31,6 +30,8 @@ import { ClosedGroupEncryptionPairRequestMessage } from '../messages/outgoing/co
import { ClosedGroupNameChangeMessage } from '../messages/outgoing/controlMessage/group/ClosedGroupNameChangeMessage';
import { ClosedGroupNewMessage } from '../messages/outgoing/controlMessage/group/ClosedGroupNewMessage';
import { ClosedGroupRemovedMembersMessage } from '../messages/outgoing/controlMessage/group/ClosedGroupRemovedMembersMessage';
import { updateOpenGroupV1 } from '../../opengroup/opengroupV1/OpenGroup';
import { updateOpenGroupV2 } from '../../opengroup/opengroupV2/OpenGroupUpdate';
export interface GroupInfo {
id: string;
@ -89,7 +90,12 @@ export async function initiateGroupUpdate(
);
if (convo.isPublic()) {
await updateOpenGroup(convo, groupName, avatar);
if (convo.isOpenGroupV1()) {
await updateOpenGroupV1(convo, groupName, avatar);
} else {
await updateOpenGroupV2(convo, groupName, avatar);
}
return;
}
const isMediumGroup = convo.isMediumGroup();

@ -165,7 +165,7 @@ export const sendViaOnion = async (
// port: url.port,
};
window.log.debug('sendViaOnion payloadObj ==> ', payloadObj);
// window.log.debug('sendViaOnion payloadObj ==> ', payloadObj);
result = await sendOnionRequestLsrpcDest(
0,

@ -28,7 +28,7 @@ export class MessageSentHandler {
serverId,
isPublic: true,
sent: true,
sent_at: serverTimestamp,
sent_at: serverTimestamp, // we quote by sent_at, so we MUST sent_at: serverTimestamp
sync: true,
synced: true,
sentSync: true,

@ -53,8 +53,7 @@ export class SwarmPolling {
public start(): void {
this.loadGroupIds();
//FIXME audric
// void this.pollForAllKeys();
void this.pollForAllKeys();
}
public addGroupId(pubkey: PubKey) {
@ -106,11 +105,9 @@ export class SwarmPolling {
nodesToPoll = _.concat(nodesToPoll, newNodes);
}
// FXIME audric
const results = await Promise.all(
nodesToPoll.map(async (n: Snode) => {
return [];
// return this.pollNodeForKey(n, pubkey);
return this.pollNodeForKey(n, pubkey);
})
);

Loading…
Cancel
Save