Merge branch 'clearnet' of https://github.com/loki-project/session-desktop into refactor-ts-react

pull/1102/head
Vincent 5 years ago
commit 707200718d

@ -106,7 +106,6 @@ module.exports = {
updateConversation,
removeConversation,
getAllConversations,
getAllRssFeedConversations,
getAllPublicConversations,
getPublicConversationsByServer,
getPubkeysInPublicConversation,
@ -810,6 +809,7 @@ const LOKI_SCHEMA_VERSIONS = [
updateToLokiSchemaVersion3,
updateToLokiSchemaVersion4,
updateToLokiSchemaVersion5,
updateToLokiSchemaVersion6,
];
async function updateToLokiSchemaVersion1(currentVersion, instance) {
@ -999,6 +999,34 @@ async function updateToLokiSchemaVersion5(currentVersion, instance) {
console.log('updateToLokiSchemaVersion5: success!');
}
async function updateToLokiSchemaVersion6(currentVersion, instance) {
if (currentVersion >= 6) {
return;
}
console.log('updateToLokiSchemaVersion6: starting...');
await instance.run('BEGIN TRANSACTION;');
// Remove RSS Feed conversations
await instance.run(
`DELETE FROM conversations WHERE
type = 'group' AND
id LIKE 'rss://%';`
);
await instance.run(
`INSERT INTO loki_schema (
version
) values (
6
);`
);
await instance.run('COMMIT TRANSACTION;');
console.log('updateToLokiSchemaVersion6: success!');
}
async function updateLokiSchema(instance) {
const result = await instance.get(
"SELECT name FROM sqlite_master WHERE type = 'table' AND name='loki_schema';"
@ -1905,17 +1933,6 @@ async function getAllPrivateConversations() {
return map(rows, row => jsonToObject(row.json));
}
async function getAllRssFeedConversations() {
const rows = await db.all(
`SELECT json FROM conversations WHERE
type = 'group' AND
id LIKE 'rss://%'
ORDER BY id ASC;`
);
return map(rows, row => jsonToObject(row.json));
}
async function getAllPublicConversations() {
const rows = await db.all(
`SELECT json FROM conversations WHERE

@ -456,7 +456,6 @@
<script type='text/javascript' src='js/read_syncs.js'></script>
<script type='text/javascript' src='js/models/messages.js'></script>
<script type='text/javascript' src='js/models/conversations.js'></script>
<script type='text/javascript' src='js/models/blockedNumbers.js'></script>
<script type='text/javascript' src='js/expiring_messages.js'></script>
<script type='text/javascript' src='js/chromium.js'></script>

@ -456,7 +456,6 @@
<script type='text/javascript' src='js/read_syncs.js'></script>
<script type='text/javascript' src='js/models/messages.js'></script>
<script type='text/javascript' src='js/models/conversations.js'></script>
<script type='text/javascript' src='js/models/blockedNumbers.js'></script>
<script type='text/javascript' src='js/expiring_messages.js'></script>
<script type='text/javascript' src='js/chromium.js'></script>

@ -216,14 +216,6 @@
if (specialConvInited) {
return;
}
const rssFeedConversations = await window.Signal.Data.getAllRssFeedConversations(
{
ConversationCollection: Whisper.ConversationCollection,
}
);
rssFeedConversations.forEach(conversation => {
window.feeds.push(new window.LokiRssAPI(conversation.getRssSettings()));
});
const publicConversations = await window.Signal.Data.getAllPublicConversations(
{
ConversationCollection: Whisper.ConversationCollection,
@ -1480,6 +1472,10 @@
return;
}
if (firstRun) {
window.readyForUpdates();
}
if (!Whisper.Registration.everDone()) {
return;
}

@ -1,83 +0,0 @@
/* global storage, _ */
/* global _: false */
/* global Backbone: false */
/* global BlockedNumberController: false */
/* global storage: false */
/* global Whisper: false */
/* eslint-disable more/no-then */
// eslint-disable-next-line func-names
(function() {
'use strict';
window.Whisper = window.Whisper || {};
const BLOCKED_NUMBERS_ID = 'blocked';
const BLOCKED_GROUPS_ID = 'blocked-groups';
storage.isBlocked = number => {
const numbers = storage.get(BLOCKED_NUMBERS_ID, []);
return _.include(numbers, number);
};
storage.getBlockedNumbers = () => storage.get(BLOCKED_NUMBERS_ID, []);
storage.addBlockedNumber = number => {
const numbers = storage.get(BLOCKED_NUMBERS_ID, []);
if (_.include(numbers, number)) {
return;
}
window.log.info('adding', number, 'to blocked list');
storage.put(BLOCKED_NUMBERS_ID, numbers.concat(number));
};
storage.removeBlockedNumber = number => {
const numbers = storage.get(BLOCKED_NUMBERS_ID, []);
if (!_.include(numbers, number)) {
return;
}
window.log.info('removing', number, 'from blocked list');
storage.put(BLOCKED_NUMBERS_ID, _.without(numbers, number));
};
storage.isGroupBlocked = groupId => {
const groupIds = storage.get(BLOCKED_GROUPS_ID, []);
return _.include(groupIds, groupId);
};
storage.removeBlockedGroup = groupId => {
const groupIds = storage.get(BLOCKED_GROUPS_ID, []);
if (!_.include(groupIds, groupId)) {
return;
}
window.log.info(`removing group(${groupId} from blocked list`);
storage.put(BLOCKED_GROUPS_ID, _.without(groupIds, groupId));
};
Whisper.BlockedNumber = Backbone.Model.extend({
defaults() {
return {
number: '',
};
},
block() {
return BlockedNumberController.block(this.number);
},
unblock() {
return BlockedNumberController.unblock(this.number);
},
});
Whisper.BlockedNumberCollection = Backbone.Collection.extend({
model: Whisper.BlockedNumber,
comparator(m) {
return m.get('number');
},
getModel(number) {
return this.models.find(m => m.get('number') === number);
},
});
})();

@ -124,7 +124,6 @@ module.exports = {
getAllConversations,
getAllConversationIds,
getAllPrivateConversations,
getAllRssFeedConversations,
getAllPublicConversations,
getPublicConversationsByServer,
getPubkeysInPublicConversation,
@ -811,14 +810,6 @@ async function getAllConversationIds() {
return ids;
}
async function getAllRssFeedConversations({ ConversationCollection }) {
const conversations = await channels.getAllRssFeedConversations();
const collection = new ConversationCollection();
collection.add(conversations);
return collection;
}
async function getAllPublicConversations({ ConversationCollection }) {
const conversations = await channels.getAllPublicConversations();

@ -1533,6 +1533,10 @@ class LokiPublicChannelAPI {
});
if (res.err || !res.response || !res.response.data) {
if (res.statusCode === 403) {
// token is now invalid
this.serverAPI.getOrRefreshServerToken(true);
}
return;
}
@ -1656,6 +1660,10 @@ class LokiPublicChannelAPI {
!res.response.data ||
!res.response.meta
) {
if (res.statusCode === 403) {
// token is now invalid
this.serverAPI.getOrRefreshServerToken(true);
}
if (res.err) {
log.error(`pollOnceForDeletions Error ${res.err}`);
} else {
@ -1852,6 +1860,10 @@ class LokiPublicChannelAPI {
});
if (res.err || !res.response) {
if (res.statusCode === 403) {
// token is now invalid
this.serverAPI.getOrRefreshServerToken(true);
}
log.error(
`app_dot_net:::pollOnceForMessages - Could not get messages from`,
this.serverAPI.baseServerUrl,

@ -1,162 +0,0 @@
/* eslint-disable no-await-in-loop */
/* eslint-disable no-loop-func */
/* global log, window, textsecure */
const EventEmitter = require('events');
const PER_MIN = 60 * 1000;
const PER_HR = 60 * PER_MIN;
const RSS_POLL_EVERY = 1 * PER_HR; // once an hour
function xml2json(xml) {
try {
let obj = {};
if (xml.children.length > 0) {
for (let i = 0; i < xml.children.length; i += 1) {
const item = xml.children.item(i);
const { nodeName } = item;
if (typeof obj[nodeName] === 'undefined') {
obj[nodeName] = xml2json(item);
} else {
if (typeof obj[nodeName].push === 'undefined') {
const old = obj[nodeName];
obj[nodeName] = [];
obj[nodeName].push(old);
}
obj[nodeName].push(xml2json(item));
}
}
} else {
obj = xml.textContent;
}
return obj;
} catch (e) {
log.error(e.message);
}
return {};
}
class LokiRssAPI extends EventEmitter {
constructor(settings) {
super();
// properties
this.feedUrl = settings.RSS_FEED;
this.groupId = settings.CONVO_ID;
this.feedTitle = settings.title;
this.closeable = settings.closeable;
// non configureable options
this.feedTimer = null;
// initial set up
this.getFeed();
}
async getFeed() {
// deal with file server proxy hardcoding
const map = {
'https://loki.network/category/messenger-updates/feed/':
'loki/v1/rss/messenger',
'https://loki.network/feed/': 'loki/v1/rss/loki',
};
if (map[this.feedUrl] === undefined) {
log.warn('LokiRssAPI unsupported rss feed', this.feedUrl);
return;
}
const result = await window.tokenlessFileServerAdnAPI.serverRequest(
map[this.feedUrl]
);
if (!result) {
log.error('LokiRssAPI empty rss proxy response');
return;
}
if (!result.response) {
log.error('LokiRssAPI rss proxy error, no response', result);
return;
}
if (!result.response.data) {
log.error(
'LokiRssAPI rss proxy error, no data, response',
typeof result.response,
result.response
);
return;
}
const responseXML = result.response.data;
let feedDOM = {};
try {
feedDOM = await new window.DOMParser().parseFromString(
responseXML,
'text/xml'
);
} catch (e) {
log.error('LokiRssAPI xml parsing error', e, responseXML);
return;
}
const feedObj = xml2json(feedDOM);
let receivedAt = new Date().getTime();
if (!feedObj || !feedObj.rss || !feedObj.rss.channel) {
log.error(
'LokiRssAPI rss structure error',
feedObj,
feedDOM,
responseXML
);
return;
}
if (!feedObj.rss.channel.item) {
// no records, not an error
return;
}
if (feedObj.rss.channel.item.constructor !== Array) {
// Treat single record as array for consistency
feedObj.rss.channel.item = [feedObj.rss.channel.item];
}
feedObj.rss.channel.item.reverse().forEach(item => {
// log.debug('item', item)
const pubDate = new Date(item.pubDate);
// if we use group style, we can put the title in the source
const messageData = {
isSessionRequest: false,
source: this.groupId,
sourceDevice: 1,
timestamp: pubDate.getTime(),
serverTimestamp: pubDate.getTime(),
receivedAt,
isRss: true,
message: {
body: `<h2>${item.title} </h2>${item.description}`,
attachments: [],
group: {
id: this.groupId,
type: textsecure.protobuf.GroupContext.Type.DELIVER,
},
flags: 0,
expireTimer: 0,
profileKey: null,
timestamp: pubDate.getTime(),
received_at: receivedAt,
sent_at: pubDate.getTime(),
quote: null,
contact: [],
preview: [],
profile: null,
},
};
receivedAt += 1; // Ensure different arrival times
this.emit('rssMessage', {
message: messageData,
});
});
const ref = this;
function callTimer() {
ref.getFeed();
}
this.feedTimer = setTimeout(callTimer, RSS_POLL_EVERY);
}
}
module.exports = LokiRssAPI;

@ -2,7 +2,7 @@
"name": "session-desktop",
"productName": "Session",
"description": "Private messaging from your desktop",
"version": "1.0.9",
"version": "1.1.2",
"license": "GPL-3.0",
"author": {
"name": "Loki Project",
@ -312,7 +312,7 @@
"!**/node_modules/*/build/**",
"!**/*.{o,hprof,orig,pyc,pyo,rbc}",
"!**/._*",
"!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,__pycache__,thumbs.db,.gitignore,.gitattributes,.editorconfig,.flowconfig,.yarn-metadata.json,.idea,appveyor.yml,.travis.yml,circle.yml,npm-debug.log,.nyc_output,yarn.lock,.yarn-integrity}",
"!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,__pycache__,thumbs.db,.gitignore,.gitattributes,.editorconfig,.flowconfig,.yarn-metadata.json,.idea,appveyor.yml,.travis.yml,circle.yml,npm-debug.log,.nyc_output,yarn.lock,.yarn-integrity,.map}",
"node_modules/spellchecker/build/Release/*.node",
"node_modules/websocket/build/Release/*.node",
"node_modules/socks/build/*.js",

@ -21,19 +21,18 @@ window.getEnvironment = () => config.environment;
window.getVersion = () => config.version;
window.getAppInstance = () => config.appInstance;
// So far we're only using this for Signal.Types
const Signal = require('./js/modules/signal');
const electron = require('electron');
const ipc = electron.ipcRenderer;
window.Signal = Signal.setup({
Attachments: null,
userDataPath: null,
getRegionCode: () => null,
});
window.Signal.Logs = require('./js/modules/logs');
const {
SessionPasswordPrompt,
} = require('./ts/components/session/SessionPasswordPrompt');
window.Signal = {
Components: {
SessionPasswordPrompt,
},
}
window.CONSTANTS = {
MAX_LOGIN_TRIES: 3,

@ -358,8 +358,6 @@ window.LokiPublicChatAPI = require('./js/modules/loki_public_chat_api');
window.LokiFileServerAPI = require('./js/modules/loki_file_server_api');
window.LokiRssAPI = require('./js/modules/loki_rss_api');
window.mnemonic = require('./libloki/modules/mnemonic');
const WorkerInterface = require('./js/modules/util_worker_interface');

@ -503,7 +503,6 @@
<script type="text/javascript" src="../js/models/messages.js" data-cover></script>
<script type="text/javascript" src="../js/models/conversations.js" data-cover></script>
<script type="text/javascript" src="../js/models/blockedNumbers.js" data-cover></script>
<script type="text/javascript" src="../js/conversation_controller.js" data-cover></script>
<script type="text/javascript" src="../js/message_controller.js" data-cover></script>
<script type="text/javascript" src="../js/keychange_listener.js" data-cover></script>

@ -236,7 +236,7 @@ export async function processDecrypted(envelope: EnvelopePlus, decrypted: any) {
/* tslint:disable:no-bitwise */
}
function isMessageEmpty(message: SignalService.DataMessage) {
export function isMessageEmpty(message: SignalService.DataMessage) {
const {
flags,
body,
@ -251,7 +251,8 @@ function isMessageEmpty(message: SignalService.DataMessage) {
return (
!flags &&
_.isEmpty(body) &&
// FIXME remove this hack to drop auto friend requests messages in a few weeks 15/07/2020
isBodyEmpty(body) &&
_.isEmpty(attachments) &&
_.isEmpty(group) &&
_.isEmpty(quote) &&
@ -262,6 +263,16 @@ function isMessageEmpty(message: SignalService.DataMessage) {
);
}
function isBodyEmpty(body: string) {
return _.isEmpty(body) || isBodyAutoFRContent(body);
}
function isBodyAutoFRContent(body: string) {
return (
body === 'Please accept to enable messages to be synced across devices'
);
}
export async function handleDataMessage(
envelope: EnvelopePlus,
dataMessage: SignalService.IDataMessage

@ -338,22 +338,29 @@ async function onContactReceived(details: any) {
activeAt = activeAt || Date.now();
conversation.set('active_at', activeAt);
}
const ourPrimaryKey = window.storage.get('primaryDevicePubKey');
if (ourPrimaryKey) {
const secondaryDevices = await MultiDeviceProtocol.getSecondaryDevices(
ourPrimaryKey
);
if (secondaryDevices.some(device => device.key === id)) {
await conversation.setSecondaryStatus(true, ourPrimaryKey);
}
}
const devices = await MultiDeviceProtocol.getAllDevices(id);
const deviceConversations = await Promise.all(
devices.map(d =>
ConversationController.getOrCreateAndWait(d.key, 'private')
)
const primaryDevice = await MultiDeviceProtocol.getPrimaryDevice(id);
const secondaryDevices = await MultiDeviceProtocol.getSecondaryDevices(id);
const primaryConversation = await ConversationController.getOrCreateAndWait(
primaryDevice.key,
'private'
);
const secondaryConversations = await Promise.all(
secondaryDevices.map(async d => {
const secondaryConv = await ConversationController.getOrCreateAndWait(
d.key,
'private'
);
await secondaryConv.setSecondaryStatus(true, primaryDevice.key);
return conversation;
})
);
const deviceConversations = [
primaryConversation,
...secondaryConversations,
];
// triger session request with every devices of that user
// when we do not have a session with it already
deviceConversations.forEach(device => {
@ -366,23 +373,17 @@ async function onContactReceived(details: any) {
conversation.setProfileKey(profileKey);
}
if (details.blocked !== 'undefined') {
if (details.blocked) {
storage.addBlockedNumber(id);
} else {
storage.removeBlockedNumber(id);
}
}
// Do not set name to allow working with lokiProfile and nicknames
conversation.set({
// name: details.name,
color: details.color,
});
await conversation.setLokiProfile({ displayName: details.name });
if (details.name && details.name.length) {
await conversation.setLokiProfile({ displayName: details.name });
}
if (details.nickname) {
if (details.nickname && details.nickname.length) {
await conversation.setNickname(details.nickname);
}

@ -7,11 +7,16 @@ import ByteBuffer from 'bytebuffer';
import { handleEndSession } from './sessionHandling';
import { handleMediumGroupUpdate } from './mediumGroups';
import { handleMessageEvent, processDecrypted } from './dataMessage';
import {
handleMessageEvent,
isMessageEmpty,
processDecrypted,
} from './dataMessage';
import { updateProfile } from './receiver';
import { handleContacts } from './multidevice';
import { onGroupReceived } from './groups';
import { MultiDeviceProtocol } from '../session/protocols';
import { DataMessage } from '../session/messages/outgoing';
export async function handleSyncMessage(
envelope: EnvelopePlus,
@ -88,6 +93,12 @@ async function handleSentMessage(
return;
}
if (isMessageEmpty(msg as SignalService.DataMessage)) {
window.console.log('dropping empty message synced');
await removeFromCache(envelope);
return;
}
const { ConversationController } = window;
// tslint:disable-next-line no-bitwise

1
ts/window.d.ts vendored

@ -25,7 +25,6 @@ declare global {
LokiAppDotNetServerAPI: any;
LokiFileServerAPI: any;
LokiPublicChatAPI: any;
LokiRssAPI: any;
LokiSnodeAPI: any;
MessageController: any;
Session: any;

Loading…
Cancel
Save