fix: set and get profile picture from libsession
This commit is contained in:
parent
6bbb16b46d
commit
f215535f75
|
@ -37,6 +37,7 @@ async function mergeConfigsWithIncomingUpdates(
|
|||
|
||||
const wrapperId = LibSessionUtil.kindToVariant(kind);
|
||||
await GenericWrapperActions.merge(wrapperId, toMerge);
|
||||
|
||||
const needsPush = await GenericWrapperActions.needsPush(wrapperId);
|
||||
const needsDump = await GenericWrapperActions.needsDump(wrapperId);
|
||||
const messageHashes = [incomingConfig.messageHash];
|
||||
|
@ -59,7 +60,6 @@ async function handleUserProfileUpdate(result: IncomingConfResult): Promise<Inco
|
|||
}
|
||||
|
||||
const updatedProfilePicture = await UserConfigWrapperActions.getProfilePicture();
|
||||
debugger;
|
||||
const picUpdate = !isEmpty(updatedProfilePicture.key) && !isEmpty(updatedProfilePicture.url);
|
||||
await ProfileManager.updateOurProfileSync(
|
||||
updatedUserName,
|
||||
|
|
|
@ -42,14 +42,15 @@ async function updateProfileOfContact(
|
|||
|
||||
// avoid setting the display name to an invalid value
|
||||
if (existingDisplayName !== displayName && !isEmpty(displayName)) {
|
||||
console.warn(
|
||||
`updateProfileOfContact overriding old "${existingDisplayName}: with "${displayName}"`
|
||||
);
|
||||
|
||||
conversation.set('displayNameInProfile', displayName || undefined);
|
||||
await conversation.commit();
|
||||
}
|
||||
// add an avatar download job only if needed
|
||||
|
||||
debugger;
|
||||
const profileKeyHex = !profileKey || isEmpty(profileKey) ? null : toHex(profileKey);
|
||||
|
||||
await AvatarDownload.addAvatarDownloadJobIfNeeded({
|
||||
profileKeyHex,
|
||||
profileUrl,
|
||||
|
|
|
@ -21,6 +21,10 @@ export type StartProcessingResult = 'job_in_progress' | 'job_deferred' | 'job_st
|
|||
|
||||
export type AddJobResult = 'job_deferred' | 'job_started';
|
||||
|
||||
function jobToLogId<T extends TypeOfPersistedData>(jobRunner: JobRunnerType, job: PersistedJob<T>) {
|
||||
return `id: "${job.persistedData.identifier}" (type: "${jobRunner}")`;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is used to plan jobs and make sure they are retried until the success.
|
||||
* By having a specific type, we can find the logic to be run by that type of job.
|
||||
|
@ -79,7 +83,7 @@ export class PersistedJobRunner<T extends TypeOfPersistedData> {
|
|||
|
||||
if (this.jobsScheduled.find(j => j.persistedData.identifier === job.persistedData.identifier)) {
|
||||
window.log.info(
|
||||
`job runner has already a job with id:"${job.persistedData.identifier}" planned so not adding another one`
|
||||
`job runner (${this.jobRunnerType}) has already a job with id:"${job.persistedData.identifier}" planned so not adding another one`
|
||||
);
|
||||
return 'identifier_exists';
|
||||
}
|
||||
|
@ -168,7 +172,7 @@ export class PersistedJobRunner<T extends TypeOfPersistedData> {
|
|||
|
||||
private async writeJobsToDB() {
|
||||
const serialized = this.getSerializedJobs();
|
||||
window.log.warn('writing to db', serialized);
|
||||
window.log.warn(`writing to db for "${this.jobRunnerType}": `, serialized);
|
||||
await Data.createOrUpdateItem({
|
||||
id: this.getJobRunnerItemId(),
|
||||
value: JSON.stringify(serialized),
|
||||
|
@ -176,7 +180,6 @@ export class PersistedJobRunner<T extends TypeOfPersistedData> {
|
|||
}
|
||||
|
||||
private async addJobUnchecked(job: PersistedJob<T>) {
|
||||
console.warn('job', job);
|
||||
this.jobsScheduled.push(cloneDeep(job));
|
||||
this.sortJobsList();
|
||||
await this.writeJobsToDB();
|
||||
|
@ -254,7 +257,12 @@ export class PersistedJobRunner<T extends TypeOfPersistedData> {
|
|||
private deleteJobsByIdentifier(identifiers: Array<string>) {
|
||||
identifiers.forEach(identifier => {
|
||||
const jobIndex = this.jobsScheduled.findIndex(f => f.persistedData.identifier === identifier);
|
||||
window.log.info('deleteJobsByIdentifier job', identifier, ' index', jobIndex);
|
||||
window.log.info(
|
||||
`removing job ${jobToLogId(
|
||||
this.jobRunnerType,
|
||||
this.jobsScheduled[jobIndex]
|
||||
)} at ${jobIndex}`
|
||||
);
|
||||
|
||||
if (jobIndex >= 0) {
|
||||
this.jobsScheduled.splice(jobIndex, 1);
|
||||
|
@ -290,21 +298,40 @@ export class PersistedJobRunner<T extends TypeOfPersistedData> {
|
|||
success = await timeout(this.currentJob.runJob(), this.currentJob.getJobTimeoutMs());
|
||||
|
||||
if (success !== RunJobResult.Success) {
|
||||
throw new Error(`job ${nextJob.persistedData.identifier} failed`);
|
||||
throw new Error('return result was not "Success"');
|
||||
}
|
||||
|
||||
// here the job did not throw and didn't return false. Consider it OK then and remove it from the list of jobs to run.
|
||||
this.deleteJobsByIdentifier([this.currentJob.persistedData.identifier]);
|
||||
await this.writeJobsToDB();
|
||||
} catch (e) {
|
||||
window.log.warn(`JobRunner current ${this.jobRunnerType} failed with ${e.message}`);
|
||||
window.log.info(`${jobToLogId(this.jobRunnerType, nextJob)} failed with "${e.message}"`);
|
||||
if (
|
||||
success === RunJobResult.PermanentFailure ||
|
||||
nextJob.persistedData.currentRetry >= nextJob.persistedData.maxAttempts - 1
|
||||
) {
|
||||
if (success === RunJobResult.PermanentFailure) {
|
||||
window.log.info(
|
||||
`${jobToLogId(this.jobRunnerType, nextJob)}:${
|
||||
nextJob.persistedData.currentRetry
|
||||
} permament failure for job`
|
||||
);
|
||||
} else {
|
||||
window.log.info(
|
||||
`Too many failures for ${jobToLogId(
|
||||
this.jobRunnerType,
|
||||
nextJob
|
||||
)} out of nextJob.persistedData.maxAttempts`
|
||||
);
|
||||
}
|
||||
// we cannot restart this job anymore. Remove the entry completely
|
||||
this.deleteJobsByIdentifier([nextJob.persistedData.identifier]);
|
||||
} else {
|
||||
window.log.info(
|
||||
`Rescheduling ${jobToLogId(this.jobRunnerType, nextJob)} in ${
|
||||
nextJob.persistedData.delayBetweenRetries
|
||||
}...`
|
||||
);
|
||||
nextJob.persistedData.currentRetry = nextJob.persistedData.currentRetry + 1;
|
||||
// that job can be restarted. Plan a retry later with the already defined retry
|
||||
nextJob.persistedData.nextAttemptTimestamp =
|
||||
|
|
|
@ -60,11 +60,11 @@ async function addAvatarDownloadJobIfNeeded({
|
|||
profileKeyHex: string | null | undefined;
|
||||
}) {
|
||||
if (profileKeyHex && shouldAddAvatarDownloadJob({ pubkey, profileUrl, profileKeyHex })) {
|
||||
debugger;
|
||||
const avatarDownloadJob = new AvatarDownloadJob({
|
||||
conversationId: pubkey,
|
||||
profileKeyHex,
|
||||
profilePictureUrl: profileUrl || null,
|
||||
nextAttemptTimestamp: Date.now(),
|
||||
});
|
||||
window.log.debug(
|
||||
`addAvatarDownloadJobIfNeeded: adding job download for ${pubkey}:${profileUrl}:${profileKeyHex} `
|
||||
|
@ -130,8 +130,6 @@ class AvatarDownloadJob extends PersistedJob<AvatarDownloadPersistedData> {
|
|||
return RunJobResult.PermanentFailure;
|
||||
}
|
||||
|
||||
debugger;
|
||||
|
||||
let conversation = getConversationController().get(convoId);
|
||||
if (!conversation) {
|
||||
// return true so we do not retry this task.
|
||||
|
@ -171,12 +169,26 @@ class AvatarDownloadJob extends PersistedJob<AvatarDownloadPersistedData> {
|
|||
});
|
||||
conversation = getConversationController().getOrThrow(convoId);
|
||||
|
||||
if (!downloaded.data.byteLength) {
|
||||
window.log.debug(`[profileupdate] downloaded data is empty for ${conversation.id}`);
|
||||
return RunJobResult.RetryJobIfPossible; // so we retry this job
|
||||
}
|
||||
|
||||
// null => use placeholder with color and first letter
|
||||
let path = null;
|
||||
|
||||
try {
|
||||
const profileKeyArrayBuffer = fromHexToArray(this.persistedData.profileKeyHex);
|
||||
const decryptedData = await decryptProfile(downloaded.data, profileKeyArrayBuffer);
|
||||
let decryptedData: ArrayBuffer;
|
||||
try {
|
||||
decryptedData = await decryptProfile(downloaded.data, profileKeyArrayBuffer);
|
||||
} catch (decryptError) {
|
||||
window.log.info(
|
||||
`[profileupdate] failed to decrypt downloaded data ${conversation.id} with provided profileKey`
|
||||
);
|
||||
// if we cannot decrypt the content, there is no need to keep retrying.
|
||||
return RunJobResult.PermanentFailure;
|
||||
}
|
||||
|
||||
window.log.info(
|
||||
`[profileupdate] about to auto scale avatar for convo ${conversation.id}`
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { from_string } from 'libsodium-wrappers-sumo';
|
||||
import { compact, groupBy, isArray, isEmpty, isNumber, isString, uniq } from 'lodash';
|
||||
import { v4 } from 'uuid';
|
||||
import { UserUtils } from '../..';
|
||||
|
@ -12,6 +11,7 @@ import { getConversationController } from '../../../conversations';
|
|||
import { SharedConfigMessage } from '../../../messages/outgoing/controlMessage/SharedConfigMessage';
|
||||
import { MessageSender } from '../../../sending/MessageSender';
|
||||
import { LibSessionUtil, OutgoingConfResult } from '../../libsession/libsession_utils';
|
||||
import { fromHexToArray } from '../../String';
|
||||
import { runners } from '../JobRunner';
|
||||
import {
|
||||
AddJobCheckReturn,
|
||||
|
@ -116,10 +116,6 @@ function resultsToSuccessfulChange(
|
|||
request.destination
|
||||
) {
|
||||
// a message was posted. We need to add it to the tracked list of hashes
|
||||
console.warn(
|
||||
`messagePostedHashes for j:${j}; didDeleteOldConfigMessages:${didDeleteOldConfigMessages}: `,
|
||||
messagePostedHashes
|
||||
);
|
||||
const updatedHashes: Array<string> = didDeleteOldConfigMessages
|
||||
? [messagePostedHashes]
|
||||
: uniq(compact([...request.allOldHashes, messagePostedHashes]));
|
||||
|
@ -132,7 +128,6 @@ function resultsToSuccessfulChange(
|
|||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('eeee', e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
@ -153,7 +148,6 @@ async function buildAndSaveDumpsToDB(changes: Array<SuccessfulChange>): Promise<
|
|||
continue;
|
||||
}
|
||||
const dump = await GenericWrapperActions.dump(variant);
|
||||
console.warn('change.updatedHash', change.updatedHash);
|
||||
await ConfigDumpData.saveConfigDump({
|
||||
data: dump,
|
||||
publicKey: change.publicKey,
|
||||
|
@ -205,7 +199,8 @@ class ConfigurationSyncJob extends PersistedJob<ConfigurationSyncPersistedData>
|
|||
await UserConfigWrapperActions.setName(name || '');
|
||||
|
||||
if (profileKey && pointer) {
|
||||
await UserConfigWrapperActions.setProfilePicture(pointer, from_string(profileKey));
|
||||
const profileKeyArray = fromHexToArray(profileKey);
|
||||
await UserConfigWrapperActions.setProfilePicture(pointer, profileKeyArray);
|
||||
} else {
|
||||
await UserConfigWrapperActions.setProfilePicture('', new Uint8Array());
|
||||
}
|
||||
|
@ -235,9 +230,6 @@ class ConfigurationSyncJob extends PersistedJob<ConfigurationSyncPersistedData>
|
|||
})
|
||||
);
|
||||
|
||||
console.warn(
|
||||
`ConfigurationSyncJob sendToPubKeyNonDurably ${this.persistedData.identifier} returned: "${allResults}"`
|
||||
);
|
||||
// we do a sequence call here. If we do not have the right expected number of results, consider it
|
||||
|
||||
if (!isArray(allResults) || allResults.length !== singleDestChanges.length) {
|
||||
|
|
|
@ -160,7 +160,6 @@ async function pendingChangesForPubkey(pubkey: string): Promise<Array<OutgoingCo
|
|||
|
||||
const results: Array<OutgoingConfResult> = [];
|
||||
|
||||
debugger;
|
||||
for (let index = 0; index < dumps.length; index++) {
|
||||
const dump = dumps[index];
|
||||
const variant = dump.variant;
|
||||
|
|
|
@ -5,7 +5,7 @@ import { from_hex, from_string } from 'libsodium-wrappers-sumo';
|
|||
// tslint:disable: chai-vague-errors no-unused-expression no-http-string no-octal-literal whitespace no-require-imports variable-name
|
||||
import * as SessionUtilWrapper from 'session_util_wrapper';
|
||||
|
||||
describe('libsession_wrapper_contacts ', () => {
|
||||
describe('libsession_contacts', () => {
|
||||
// Note: To run this test, you need to compile the libsession wrapper for node (and not for electron).
|
||||
// To do this, you can cd to the node_module/libsession_wrapper folder and do
|
||||
// yarn configure && yarn build
|
||||
|
@ -13,7 +13,7 @@ describe('libsession_wrapper_contacts ', () => {
|
|||
|
||||
// We have to disable it by filename as nodejs tries to load the module during the import step above, and fails as it is not compiled for nodejs but for electron.
|
||||
|
||||
it('[config][contacts]', () => {
|
||||
it('libsession_contacts', () => {
|
||||
const edSecretKey = from_hex(
|
||||
'0123456789abcdef0123456789abcdef000000000000000000000000000000004cb76fdc6d32278e3f83dbf608360ecc6b65727934b85d2fb86862ff98c46ab7'
|
||||
);
|
||||
|
@ -186,7 +186,7 @@ describe('libsession_wrapper_contacts ', () => {
|
|||
expect(nicknames2).to.be.deep.eq(['(N/A)', 'Nickname 3']);
|
||||
});
|
||||
|
||||
it('[config][contacts][c]', () => {
|
||||
it('libsession_contacts_c', () => {
|
||||
const edSecretKey = from_hex(
|
||||
'0123456789abcdef0123456789abcdef000000000000000000000000000000004cb76fdc6d32278e3f83dbf608360ecc6b65727934b85d2fb86862ff98c46ab7'
|
||||
);
|
||||
|
|
|
@ -7,7 +7,7 @@ import { concatUInt8Array } from '../../../../session/crypto';
|
|||
// tslint:disable: chai-vague-errors no-unused-expression no-http-string no-octal-literal whitespace
|
||||
|
||||
describe('libsession_wrapper', () => {
|
||||
it('[config][user_profile][c]', () => {
|
||||
it('libsession_user', () => {
|
||||
// Note: To run this test, you need to compile the libsession wrapper for node (and not for electron).
|
||||
// To do this, you can cd to the node_module/libsession_wrapper folder and do
|
||||
// yarn configure && yarn build
|
||||
|
@ -46,7 +46,14 @@ describe('libsession_wrapper', () => {
|
|||
expect(picResult.key).to.be.null;
|
||||
|
||||
// Now let's go set a profile name and picture:
|
||||
conf.setProfilePicture('http://example.org/omg-pic-123.bmp', stringToUint8Array('secret'));
|
||||
conf.setProfilePicture(
|
||||
'http://example.org/omg-pic-123.bmp',
|
||||
new Uint8Array([115, 101, 99, 114, 101, 116]) // 'secret' in ascii
|
||||
);
|
||||
expect(conf.getProfilePicture().key).to.be.deep.eq(
|
||||
new Uint8Array([115, 101, 99, 114, 101, 116]) // 'secret' in ascii
|
||||
);
|
||||
|
||||
conf.setName('Kallie');
|
||||
|
||||
// Retrieve them just to make sure they set properly:
|
||||
|
@ -58,7 +65,9 @@ describe('libsession_wrapper', () => {
|
|||
const picture = conf.getProfilePicture();
|
||||
|
||||
expect(picture.url).to.be.eq('http://example.org/omg-pic-123.bmp');
|
||||
expect(picture.key).to.be.deep.eq(stringToUint8Array('secret'));
|
||||
expect(picture.key).to.be.deep.eq(
|
||||
new Uint8Array([115, 101, 99, 114, 101, 116]) // 'secret' in ascii
|
||||
);
|
||||
|
||||
// Since we've made changes, we should need to push new config to the swarm, *and* should need
|
||||
// to dump the updated state:
|
||||
|
|
|
@ -95,8 +95,8 @@ onmessage = async (e: { data: [number, ConfigWrapperObjectTypes, string, ...any]
|
|||
}
|
||||
|
||||
const wrapper = await getCorrespondingWrapper(config);
|
||||
|
||||
const fn = (wrapper as any)[action];
|
||||
|
||||
if (!fn) {
|
||||
throw new Error(
|
||||
`Worker: job "${jobId}" did not find function "${action}" on config "${config}"`
|
||||
|
|
Loading…
Reference in New Issue