sendMessage(), getOrRefreshServerToken supports forceRefresh, make modStatus a property, additional comments

pull/455/head
Ryan Tharp 6 years ago
parent dfd6039c83
commit 56a4a31ca2

@ -14,6 +14,8 @@ class LokiPublicChatAPI extends EventEmitter {
this.ourKey = ourKey;
this.servers = [];
}
// server getter/factory
findOrCreateServer(serverUrl) {
let thisServer = this.servers.find(
server => server.baseServerUrl === serverUrl
@ -25,10 +27,14 @@ class LokiPublicChatAPI extends EventEmitter {
}
return thisServer;
}
// channel getter/factory
findOrCreateChannel(serverUrl, channelId, conversationId) {
const server = this.findOrCreateServer(serverUrl);
return server.findOrCreateChannel(channelId, conversationId);
}
// deallocate resources server uses
unregisterChannel(serverUrl, channelId) {
let thisServer;
let i = 0;
@ -60,6 +66,8 @@ class LokiPublicServerAPI {
log.info(`set token ${ref.token}`);
})();
}
// channel getter/factory
findOrCreateChannel(channelId, conversationId) {
let thisChannel = this.channels.find(
channel => channel.channelId === channelId
@ -71,6 +79,8 @@ class LokiPublicServerAPI {
}
return thisChannel;
}
// deallocate resources channel uses
unregisterChannel(channelId) {
let thisChannel;
let i = 0;
@ -87,13 +97,17 @@ class LokiPublicServerAPI {
thisChannel.stopPolling = true;
}
async getOrRefreshServerToken() {
if (this.token) {
return this.token;
// get active token for this server
async getOrRefreshServerToken(forceRefresh = false) {
let token;
if (!forceRefresh) {
if (this.token) {
return this.token;
}
token = await Signal.Data.getPublicServerTokenByServerUrl(
this.baseServerUrl
);
}
let token = await Signal.Data.getPublicServerTokenByServerUrl(
this.baseServerUrl
);
if (!token) {
token = await this.refreshServerToken();
if (token) {
@ -107,27 +121,36 @@ class LokiPublicServerAPI {
return token;
}
// get active token from server (but only allow one request at a time)
async refreshServerToken() {
// if currently not in progress
if (this.tokenPromise === null) {
// set lock
this.tokenPromise = new Promise(async res => {
// request the oken
const token = await this.requestToken();
if (!token) {
res(null);
return;
}
// activate the token
const registered = await this.submitToken(token);
if (!registered) {
res(null);
return;
}
// resolve promise to release lock
res(token);
});
}
// wait until we have it set
const token = await this.tokenPromise;
// clear lock
this.tokenPromise = null;
return token;
}
// request an token from the server
async requestToken() {
const url = new URL(`${this.baseServerUrl}/loki/v1/get_challenge`);
const params = {
@ -149,6 +172,7 @@ class LokiPublicServerAPI {
return token;
}
// activate token
async submitToken(token) {
const options = {
method: 'POST',
@ -193,12 +217,14 @@ class LokiPublicChannelAPI {
this.pollForDeletions();
}
// make a request to the server
async serverRequest(endpoint, options = {}) {
const { params = {}, method, objBody, forceFreshToken = false } = options;
const url = new URL(`${this.serverAPI.baseServerUrl}/${endpoint}`);
if (options.params) {
if (params) {
url.search = new URLSearchParams(params);
}
let res;
let result;
let { token } = this.serverAPI;
if (!token) {
token = await this.serverAPI.getOrRefreshServerToken();
@ -210,38 +236,61 @@ class LokiPublicChannelAPI {
}
}
try {
const fetchOptions = {
headers: new Headers({
Authorization: `Bearer ${this.serverAPI.token}`,
}),
const fetchOptions = {};
const headers = {
Authorization: `Bearer ${this.serverAPI.token}`,
};
if (options.method) {
fetchOptions.method = options.method;
if (method) {
fetchOptions.method = method;
}
res = await nodeFetch(url, fetchOptions || undefined);
if (objBody) {
headers['Content-Type'] = 'application/json';
fetchOptions.body = JSON.stringify(objBody);
}
fetchOptions.headers = new Headers(headers);
result = await nodeFetch(url, fetchOptions || undefined);
} catch (e) {
log.info(`e ${e}`);
return {
err: e,
};
}
const response = await res.json();
let response = null;
try {
response = await result.json();
} catch (e) {
log.info(`serverRequest json arpse ${e}`);
return {
err: e,
statusCode: result.status,
};
}
// if it's a response style with a meta
if (res.status !== 200) {
if (result.status !== 200) {
if (!forceFreshToken && response.meta.code === 401) {
// copy options because lint complains if we modify this directly
const updatedOptions = options;
// force it this time
updatedOptions.forceFreshToken = true;
// retry with updated options
return this.serverRequest(endpoint, updatedOptions);
}
return {
err: 'statusCode',
statusCode: result.status,
response,
};
}
return {
statusCode: res.status,
statusCode: result.status,
response,
};
}
// get moderator status
async refreshModStatus() {
const res = serverRequest('/loki/v1/user_info');
const res = this.serverRequest('loki/v1/user_info');
// if no problems and we have data
if (!res.err && res.response && res.response.data) {
this.modStatus = res.response.data.moderator_status;
@ -251,9 +300,12 @@ class LokiPublicChannelAPI {
await conversation.setModStatus(this.modStatus);
}
// delete a message on the server
async deleteMessage(serverId) {
const res = await this.serverRequest(
this.modStatus?`loki/v1/moderation/message/${messageServerId}`:`${this.baseChannelUrl}/messages/${serverId}`,
this.modStatus
? `loki/v1/moderation/message/${serverId}`
: `${this.baseChannelUrl}/messages/${serverId}`,
{ method: 'DELETE' }
);
if (!res.err && res.response) {
@ -264,6 +316,7 @@ class LokiPublicChannelAPI {
return false;
}
// used for sending messages
getEndpoint() {
const endpoint = `${this.serverAPI.baseServerUrl}/${
this.baseChannelUrl
@ -272,7 +325,7 @@ class LokiPublicChannelAPI {
}
// update room details
async pollForChannel(source, endpoint) {
async pollForChannel() {
// groupName will be loaded from server
const url = new URL(this.baseChannelUrl);
let res;
@ -290,9 +343,6 @@ class LokiPublicChannelAPI {
Authorization: `Bearer ${token}`,
}),
};
if (method) {
options.method = method;
}
res = await nodeFetch(url, options || undefined);
} catch (e) {
log.info(`e ${e}`);
@ -322,20 +372,21 @@ class LokiPublicChannelAPI {
// start loop
let more = true;
// eslint-disable-next-line no-await-in-loop
while (more) {
// set params to from where we last checked
params.since_id = this.deleteLastId;
// grab the next 200 deletions from where we last checked
// eslint-disable-next-line no-await-in-loop
const res = await this.serverRequest(
`loki/v1/channel/${this.channelId}/deletes`,
{ params }
);
// Process rresult
// Process results
res.response.data.reverse().forEach(deleteEntry => {
// Escalate it up to the subsystem that can check to see if this has been processsed
// Escalate it up to the subsystem that can check to see if this has
// been processed
Whisper.events.trigger('deleteLocalPublicMessage', {
messageServerId: deleteEntry.message_id,
conversationId: this.conversationId,
@ -368,10 +419,9 @@ class LokiPublicChannelAPI {
if (this.lastGot) {
params.since_id = this.lastGot;
}
const res = await this.serverRequest(
`${this.baseChannelUrl}/messages`,
{ params }
);
const res = await this.serverRequest(`${this.baseChannelUrl}/messages`, {
params,
});
if (!res.err && res.response) {
let receivedAt = new Date().getTime();
@ -442,6 +492,33 @@ class LokiPublicChannelAPI {
this.pollForMessages();
}, GROUPCHAT_POLL_EVERY);
}
// create a message in the channel
async sendMessage(text, messageTimeStamp, displayName, pubKey) {
const payload = {
text,
annotations: [
{
type: 'network.loki.messenger.publicChat',
value: {
timestamp: messageTimeStamp,
// will deprecated
from: displayName,
// will deprecated
source: pubKey,
},
},
],
};
const res = await this.serverRequest(`${this.baseChannelUrl}/messages`, {
method: 'POST',
objBody: payload,
});
if (!res.err && res.response) {
return res.response.data.id;
}
return false;
}
}
module.exports = LokiPublicChatAPI;

Loading…
Cancel
Save