! Due to user-id's being randomly generated it is now much more likely that id's can't be parsed by javascript properly

Json-bigint should help alleviate this issue by correctly parsing numbers for us

- Removing url method in favor of new url property in server config model

+ Building UserConfigs and ServerConfig from typical JS Obects
This should reduce some up front complexity regarding parameters

! Fix: using new url property instead of protocol + host + port

- Reducing upfront complexity of public channels API
* Also moving to using new updated server.url property
* Channels also handles its part of updating the dom now

bigint parsing in configs now

* More switches to server.url property
This commit is contained in:
shockrah 2021-04-10 16:47:40 -07:00
parent 89bd257213
commit 72f3461341
9 changed files with 104 additions and 54 deletions

View File

@ -225,6 +225,11 @@
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"bignumber.js": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz",
"integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA=="
},
"boolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.3.tgz",
@ -656,6 +661,14 @@
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
"integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
},
"json-bigint": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
"integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
"requires": {
"bignumber.js": "^9.0.0"
}
},
"json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",

View File

@ -12,6 +12,7 @@
"bootstrap": "^4.6.0",
"got": "^11.8.2",
"jquery": "^3.6.0",
"json-bigint": "^1.0.0",
"jsonwebtoken": "^8.5.1",
"popper.js": "^1.16.1",
"typescript": "^4.2.3",

View File

@ -1,36 +1,36 @@
const { ipcRenderer } = require('electron')
const got = require('got')
const channels = require('./channels.js')
const URL = require('url')
function push_srv(remote, user, enabled) {
let classes = 'btn btn-outline-secondary btn-nav-settings'
if(!enabled) { classes += ' disabled' }
let url = URL.parse(remote['url'])
let btn = $('<input>').attr({
type: 'button',
'class': classes,
id: remote['hostname'],
id: url.host,
value: remote['name']
})
$('#server-list').append(btn)
let cb = async () => { await channels.list(remote, user) }
$(`#${remote['hostname']}`).on('click', cb)
let cb = async () => { await channels.server_button_cb(remote, user) }
document.getElementById(url.host).onclick = cb
}
/**
* @param {String} protocol http|https
* @param {String} host Just the hostname one.two.xyz
* @param {u16} port Port to use
* @param {String} url http(s) url of target
* @param {String} user.secret
* @param {Number} user.id
*
* @returns {String|null} JWT
*/
async function login(protocol, host, port, user) {
const url = `${protocol}://${host}:${port}/login`
const response = await got(url, {
async function login(baseurl, user) {
const url = `${baseurl}/login`
const response = await got.post(url, {
searchParams: { id: user['id'], secret: user['secret'] },
responseType: 'json',
// If DNS is seriously taking this long we honestly should just give up
@ -55,13 +55,14 @@ exports.init = async function() {
const user = config.data['servers'][index]['user']
try {
const jwt = await login(remote['protocol'], remote['hostname'], remote['port'], user)
console.log('remote params: ', remote)
const jwt = await login(remote['url'], user)
config.data['servers'][index]['user']['jwt'] = jwt
user['jwt'] = jwt
push_srv(remote, user, true);
push_srv(remote, user, enabled=true);
} catch (err) {
push_srv(remote, user, false)
push_srv(remote, user, enabled=false)
const e_container = { error: err, server: remote, creds: user }
console.log('Failure to communicate with server: ', e_container)
}

View File

@ -20,16 +20,6 @@ class ServerCache {
}
}
url(): String{
let url = `${this.config.protocol}://${this.config.hostname}`
// Only add the port WITH THE COLON if the config requires it
if(this.config.port) {
url += `:${this.config.port}`
}
return url
}
push_message(message: Message) {
let ref = this.messages.get(message.cid)
if(ref) {
@ -50,7 +40,7 @@ export class Cache {
add_server(hostname: String, servercfg: ServerConfig, channels: Array<Channel>, messages: Array<Message>) {
let new_entry = new ServerCache(servercfg, channels, messages)
this.servers.set(servercfg.hostname, new_entry)
this.servers.set(servercfg.url, new_entry)
}
add_message(hostname: String, message: Message) {

View File

@ -1,6 +1,8 @@
// Requesting channel data here
const { Channel } = require('./types')
const $ = require('jquery')
const got = require('got')
const URL = require('url')
const msg = require('./messages.js')
@ -9,6 +11,10 @@ const ANY_CHANNEL = 0
const VOICE_KIND = 1
const TEXT_KIND = 2
exports.ANY_CHANNEL = ANY_CHANNEL
exports.VOICE_KIND = VOICE_KIND
exports.TEXT_KIND = TEXT_KIND
/**
* Channel button id's have the format of ${hostname}:${channel['name']}
@ -27,18 +33,20 @@ const TEXT_KIND = 2
* @param {i32} channel.kind
*/
function push(server, user, channel) {
let remote = URL.parse(server.url)
let chan_id = `${remote.hostname}:${channel['name']}`
$('#channels-list').append(
$('<li>').append(
$('<p>').append(
$('<button>').attr({
'class': 'btn btn-outline-secondary btn-nav-settings channel-btn',
id: `${server.hostname}:${channel['name']}`,
id: chan_id,
}).text(channel['name'])
)
)
)
// Not using jquery for this because it breaks with weird id names really easily
let ref = document.getElementById(`${server.hostname}:${channel['name']}`)
let ref = document.getElementById(chan_id)
ref.addEventListener('click', () => {
// now for the actual handler where we deal with clicks
$('#channel-name').text('#' + channel['name'])
@ -58,34 +66,59 @@ function push(server, user, channel) {
* Listener callback for actually getting a list of channels
* @param {Object} server Object containing server configuration
* @param {Object} user Object containing user access data
* @param {Number} kind
*
*/
exports.list = async function(server, user) {
async function list(server, user, kind) {
// TODO: add some kind of caching system here: should probably check for some kind of cache here but hey fuck it right?
// TODO: caching bro
$('#channels-list').html('')
$('#server-name').text(server['name'])
try {
const url = `${server['protocol']}://${server['hostname']}:${server['port']}/channels/list`
const text_channel_response = await got(url, {
searchParams: { id: user['id'], jwt: user['jwt'], kind: TEXT_KIND },
const url = `${server['url']}/channels/list`
const response = await got(url, {
searchParams: { id: user['id'], jwt: user['jwt'], kind: kind },
responseType: 'json'
})
let text_channels = text_channel_response.body['channels']
console.log('text: ', text_channels)
let channels_json = response.body['channels']
const channels = text_channels
for(const channel of channels) {
console.log(channel)
push(server, user, channel)
let channels_parsed = []
for(const chan of channels_json) {
console.log("channel: ", chan)
let c = new Channel(chan['name'], chan['kind'], chan['id'], chan['desc'])
channels_parsed.push(c)
}
return channels_parsed
} catch (err) {
console.log(err)
console.log(err['name'])
return []
}
}
/**
* @param {List<Channel>}
*/
async function assemble_channels_dom(channels) {
for(const channel of channels) {
console.log(channel)
push(server, user, channel)
}
}
/**
* @param {String} remote.url
* @param {String} user.id
* @param {String} user.jwt
*/
exports.server_button_cb = async function(remote, user) {
let vc = await list(remote, user, VOICE_KIND)
let tc = await list(remote, user, TEXT_KIND)
vc.push(...tc)
for(const chan of vc) {
push(remote, user, chan)
}
}

View File

@ -2,6 +2,10 @@ const { ArgumentParser } = require('argparse')
const fs = require('fs').promises
const syncFs = require('fs')
// required because freechat by default uses i64/u64 in json payloads
// timestamps will get especially rekt'd if we don't parse things correctly
const JSONBig = require('json-bigint')
class Config {
/**
*
@ -38,7 +42,7 @@ exports.from_cli_parser = function(parser) {
// Allow errors from here to bubble up instead of handling them
fs.readFile(path).then(file => {
const json = JSON.parse(file)
const json = JSONBig.parse(file)
for(const key of Object.keys(json)) {
ret.data[key] = json[key]

View File

@ -34,9 +34,7 @@ function rebind_message_box(server, auth, channel_id) {
* @param {String} auth.jwt | jwt for quick auth
* @param {u64} auth.id user | id required by most/all endpoints
*
* @param {String} server.hostname | Hostname of target server
* @param {u16} server.port | Port to use for server
* @param {String} server.protocol | http/https (no colon)
* @param {String} server.url | Url of target server
*
* @param {u64} channel_id | Channel id to query
* @param {i64} start_time | Unix time to start fetching messages from
@ -47,7 +45,7 @@ function rebind_message_box(server, auth, channel_id) {
* @throws HTTPResponseError
*/
async function get_range(auth, server, channel_id, start_time, end_time, limit) {
const url = `${server.protocol}://${server.hostname}:${server.port}/message/get_range`
const url = `${server.url}/message/get_range`
const response = await got(url, {
searchParams: {

View File

@ -17,9 +17,7 @@ exports.add_server_to_config = async function() {
try {
await auth.login(
data['server']['protocol'],
data['server']['host'],
data['server']['port'],
data['server']['url'],
data['user']
)
$('#admni-json-err').text('=|:^)')

View File

@ -48,15 +48,27 @@ export class Channel {
}
export class ServerConfig {
hostname: String
port: Number
protocol: String
url: String
name: String
description: String
constructor(protocol: String, hostname: String, port: Number) {
this.protocol = protocol
this.hostname = hostname
this.port = port
constructor(json: Object) {
this.url = json['url']
this.name = json['name']
this.description = json['description']
}
}
export class UserConfig {
id: Number
jwt: String|null
permissions: Number
secret: String
constructor(json: Object) {
this.id = json['id']
this.jwt = json['jwt']
this.permissions = json['permissions']
this.secret = json['secret']
}
}