Compare commits

...

10 Commits

Author SHA1 Message Date
6992c64179 Banner 2023-05-06 21:00:20 -07:00
shockrah
6d51f5ae61 * Implementing change to fix duplicate key entries in jwt table 2021-09-23 10:40:34 -07:00
shockrah
25692b6b92 * UserConfig now stores no numbers(all strings)
This is to avoid type coercion and loss of precision
2021-09-23 10:31:59 -07:00
shockrah
68198cd300 * Fixing EventEmitter import
+ More safety checks in Cache.update_channels
2021-09-23 10:31:19 -07:00
shockrah
3472e4d7c7 - Removing unused code
* Fixing issue with json integers being mis represented
2021-09-23 10:30:41 -07:00
shockrah
be0dc39042 + Tsconfig with some semi strict rules
Keeping the config lenient for now because more changes have to happen first
2021-09-23 10:30:08 -07:00
shockrah
33b8bcd180 * Updating tslib and wslib 2021-09-23 10:29:31 -07:00
shockrah
3cf77300b6 + Readme
* Fixing message field name to reflect its actualy key name
type -> content_type
2021-08-28 14:23:27 -07:00
shockrah
fcd48a36a1 + More comprehensive overview section 2021-07-05 17:07:41 -07:00
shockrah
a69ad24a45 + Badge structure docs
Also this is a new pattern but I'm going to start actually using those anchor tags
to self link to other places in the page.

+ /badge/new endpoint docs
+ /badge/delete endpoint docs
+ /badge/update/name endpoint docs
+ /badge/update/color endpoint docs
+ /badge/update/perms endpoint docs

! Small point but apparantly this layout is somewhat printer friendly
:^) Just thought that was kinda neat.
2021-07-01 21:09:26 -07:00
17 changed files with 263 additions and 55 deletions

View File

@ -0,0 +1,135 @@
---
title: Badges
anchor: badges-ep
weight: 19
---
### `/badge/new`
It should be noted that while alpha values are technically valid it is up to
individual clients to decide what to do with that value. Personally I suggest not
doing anything with the alpha value so that it doesn't matter but that is up to
the client developer.
* Required query string parameters:
* badge\_name: String
* Name to assign to the new badge
* badge\_perms: u64
* Permissions mask which apply to the badge
* Semi optional query string parameter:
* badge\_color: u32
* If not included the color will default to `0xffffffff`
* Required permissions
* NEW\_BADGE
* Returns
* A new [badge](#badges) behind the JSON key `badge`.
### `/badge/delete`
* Required query string parameters:
* id: u64
* ID of the target badge to delete
* Required permissions
* DELETE\_BADGE
* Returns
* HTTP 200 on success
Example:
```
> POST /badge/new
< {
< "badge": {
< "id": 1,
< "name": "badge-name-here",
< "color": 1234,
< "perms": 1234,
< }
< }
```
### `/badge/list`
* No query string required.
* No required permissions, only that the client have a valid JWT.
* Returns
* Array of [Badges](#badges) behind the JSON key `badges`.
Example:
```
> GET /badge/list
< {
< "badges": [
< {
< "id": 1,
< "name": "badge-name-here",
< "color": 1234,
< "perms": 1234,
< },
< ...
< ]
< }
```
### `/badge/update/color`
* Required query string parameters:
* badge\_id: u64
* ID of the target badge to update.
* badge\_color: u32
* The new color to update to
* Required permissions:
* UPDATE\_COLOR\_BADGE
* Returns:
* HTTP 200
### `/badge/update/name`
* Required query string parameters:
* badge\_id: u64
* ID of the target badge toupdate.
* badge\_name: String
* The new badge name to assign.
* Required permissions:
* UPDATE\_NAME\_BADGE
### `/badge/update/perms`
* Required query string parameters:
* badge\_id: u64
* ID of the target badge toupdate.
* badge\_perms: u64
* Represented as a regular integer this is the bitmap of permissions which apply to the badge
* Required permissions:
* UPDATE\_PERMS\_BADGE

View File

@ -4,6 +4,40 @@ anchor: overview
weight: 5 weight: 5
--- ---
For the source code refer to the official [Gitlab Repository](https://gitlab.com/shockrah/freechat/) _For the source code refer to the official [Gitlab repository here](https://gitlab.com/shockrah/freechat/)_.
## What is Freechat
A platform for free and open chatting.
The code is free, the protocol is simple and its all for free, like free beer _and_ free as in freedom, now and always.
## Features
* Text channels - to keep discussion organized
* Simple invite system - just a simple invite link will do.
* Powerful configuration options
For server owners: Don't like a feature? Turn it off.
For users: connections over TLS/TOR/SOCK5 or whatever other standard you want to use is allowed.
## Upcoming Features
* **Voice channels** - Currently the only thing being waited on is catching up the official client to the REST API standard(like 1 week) if you're reading this.
* **Video channels** - This one is admittedly far off but will be coming after voice channels are done
## What Tech is Freechat built on?
Freechat and its standard is built on HTTP for the most part.
Application message payloads are most typically found in the HTTP body as JSON data however, some HTTP endpoints do return any kind of JSON data as there is no real need to.
For this reason developers should familiarize themselves with the standard to avoid errors.
There is also a Websocket portion to the standard which allows for real time communications such as voice chat and live chat updates.
## About this page
This page basically outlines what data is sent to and from each HTTP endpoint as well as what common patterns can be found in the standard.
There is also section

View File

@ -0,0 +1,14 @@
---
title: Badges
anchor: badges
weight: 55
---
Name | Type
:--------:|:-------:
`name` | `String`
`id` | `u64`
`color` | `u32`
`perms` | `u64`

View File

@ -13,6 +13,7 @@ Channels are made up of the following components
name | `String` name | `String`
kind | `i32` kind | `i32`
description| `String` description| `String`
badge\_ids| `Array<u32>`
Channels have two valid types or (more semantically) `kind` values: Channels have two valid types or (more semantically) `kind` values:

View File

@ -9,7 +9,7 @@ weight: 40
id | `u64` id | `u64`
time | `i64` time | `i64`
content | `String` content | `String`
type | `String` content_type | `String`
author_id | `u64` author_id | `u64`
channel_id | `u64` channel_id | `u64`

View File

@ -14,10 +14,11 @@ Name | Type
secret | `String` secret | `String`
status | `i32` status | `i32`
permissions| `u64` permissions| `u64`
badge\_ids | `Array<u32>`
### JWT ### JWT
This data is retrieved after a sucessful `/login` hit. This data is retrieved after a successful `/login` hit.
Name | Type Name | Type
:-----:|:------: :-----:|:------:
@ -31,6 +32,7 @@ This data is retrieved after a sucessful `/login` hit.
name | `String` name | `String`
status | `i32` status | `i32`
permissions| `u64` permissions| `u64`
badge\_ids | `Array<u32>`
For users _without_ the `USER_FETCH` permission the only two fields with actual data is `id` and `name`. The other fields will be set to 0. For users _without_ the `USER_FETCH` permission the only two fields with actual data is `id` and `name`. The other fields will be set to 0.

11
docs/readme.md Normal file
View File

@ -0,0 +1,11 @@
# Freechat Wiki Source Code
This directory basically contains all the required code to build the wiki page
which is found at https://freechat.shockrah.xyz
## Printing/PDF Format
While I don't provide a pdf format of the documentation at the moment the main
API reference is somewhat printer friendly.
If anyone wants to provide a script to provide the website in other formats
it would be greatly appreciated.

View File

@ -763,9 +763,9 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}, },
"normalize-url": { "normalize-url": {
"version": "4.5.0", "version": "4.5.1",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz",
"integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA=="
}, },
"npm-conf": { "npm-conf": {
"version": "1.1.3", "version": "1.1.3",
@ -989,6 +989,11 @@
"integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==",
"dev": true "dev": true
}, },
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"tunnel": { "tunnel": {
"version": "0.0.6", "version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
@ -1041,9 +1046,9 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}, },
"ws": { "ws": {
"version": "7.4.4", "version": "7.5.5",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz",
"integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==" "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w=="
}, },
"yallist": { "yallist": {
"version": "4.0.0", "version": "4.0.0",

View File

@ -15,8 +15,9 @@
"json-bigint": "^1.0.0", "json-bigint": "^1.0.0",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"popper.js": "^1.16.1", "popper.js": "^1.16.1",
"tslib": "^2.3.1",
"typescript": "^4.2.3", "typescript": "^4.2.3",
"ws": "^7.4.4" "ws": "^7.5.5"
}, },
"devDependencies": { "devDependencies": {
"electron": "^7.3.3" "electron": "^7.3.3"

View File

@ -1,4 +1,5 @@
import * as EventEmitter from 'events'; // unused for now but maybe useful later import { EventEmitter } from 'events';
//import * as EventEmitter from 'events'; // unused for now but maybe useful later
import { ServerConfig, Message, Channel } from './types'; import { ServerConfig, Message, Channel } from './types';
import { Event } from './events'; import { Event } from './events';
@ -46,7 +47,7 @@ class ServerCache {
export class Cache extends EventEmitter { export class Cache extends EventEmitter {
// hostname -> Cache // hostname -> Cache
private servers: Map<String, ServerCache> private servers: Map<String, ServerCache>
public active_host: String public active_host: String|null
constructor() { constructor() {
super() super()
@ -61,7 +62,8 @@ export class Cache extends EventEmitter {
} }
update_channels(hostname: String, channels: Array<Channel>) : void { update_channels(hostname: String, channels: Array<Channel>) : void {
this.servers.get(hostname).channels = channels let ref = this.servers.get(hostname)
if(ref != undefined) { ref.channels = channels }
} }
last_id(hostname: String, channel_id: BigInt) : BigInt|null { last_id(hostname: String, channel_id: BigInt) : BigInt|null {

View File

@ -1,14 +1,12 @@
const { ArgumentParser } = require('argparse') const { ArgumentParser } = require('argparse')
const fs = require('fs').promises const fs = require('fs').promises
const syncFs = require('fs') const syncFs = require('fs')
const JSONBig = require('json-bigint')({storeAsString: true})
// 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 { class Config {
/** /**
* *
* TODO: change .data out for something not stupid
* @param {String} path path to config on startup * @param {String} path path to config on startup
* @param {Object} data Contains actual config data * @param {Object} data Contains actual config data
*/ */
@ -39,12 +37,13 @@ exports.from_cli_parser = function(parser) {
let ret = new Config(path, {}) let ret = new Config(path, {})
// Allow errors from here to bubble up instead of handling them // Allow errors from here to bubble up instead of handling them
fs.readFile(path).then(file => { fs.readFile(path).then(file => {
const json = JSONBig.parse(file) const json = JSONBig.parse(file)
ret.data['servers'] = []
for(const key of Object.keys(json)) { // TODO: redo this so its let 'yolo'
ret.data[key] = json[key] for(const serv of json['servers']) {
ret.data['servers'].push(serv)
} }
}) })
.catch(err => console.error(err)) .catch(err => console.error(err))
@ -52,26 +51,3 @@ exports.from_cli_parser = function(parser) {
return ret return ret
} }
/**
* Updates the config with the new object data
* Called from node's main process
*
* @param {Config} config new config data to write
* @param {String} path | set to 'default' if we're using $HOME/.config/freechat/config.json
* Set this to anything else to write changes to that specified path
*/
exports.update_file = function(config, path='default') {
if (path == 'default') {
path = `${process.env.HOME || process.env.USERPROFILE}/.config/freechat/config.json`
} else {
path = path
}
const data = JSON.stringify(config, null, 2)
fs.writeFile(path, data, function(err) {
if(err) { console.error(err) }
else { console.log('fine') }
})
}

View File

@ -54,10 +54,4 @@ export class Event {
return new Message(mid, time, content, content_type, uid, uname, cid) return new Message(mid, time, content, content_type, uid, uname, cid)
} }
// Sets up the inner channel data
private _channel(obj: Object) : Channel|null {
// todo: still require some testing to verify event data is appropriate
return null
}
} }

View File

@ -61,15 +61,15 @@ export class ServerConfig {
} }
export class UserConfig { export class UserConfig {
id: Number id: String
jwt: String|null jwt: String|null
permissions: Number permissions: String
secret: String secret: String
constructor(json: Object) { constructor(json: Object) {
this.id = json['id'] this.id = `${json['id']}`
this.jwt = json['jwt'] this.jwt = json['jwt']
this.permissions = json['permissions'] this.permissions = `${json['permissions']}`
this.secret = json['secret'] this.secret = json['secret']
} }
} }

View File

@ -0,0 +1,28 @@
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"rootDir": "./src/",
"importHelpers": true,
/* Strict Type-Checking Options */
/* "strict": true, */
/* "strictNullChecks": true, */
"strictFunctionTypes": true,
"noImplicitThis": true,
/* "alwaysStrict": true, */
/* Additional Checks */
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
/*"noUncheckedIndexedAccess": true, */
/*"noPropertyAccessFromIndexSignature": true, */
/* Module Resolution Options */
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
}
}

View File

@ -13,7 +13,12 @@ pub async fn listed(p: &Pool, id: u64, given_rng_value: &str) -> Result<bool> {
pub async fn insert(p: &Pool, id: u64, given_rng_value: &str) -> Result<()> { pub async fn insert(p: &Pool, id: u64, given_rng_value: &str) -> Result<()> {
let mut conn = p.get_conn().await?; let mut conn = p.get_conn().await?;
let q = "INSERT INTO jwt (id, rng) VALUES (:id, :rng)"; let q = "INSERT INTO jwt (id, rng) VALUES(:id, :rng)
conn.exec_drop(q, params!{"id" => id, "rng" => given_rng_value}).await?; ON DUPLICATE KEY UPDATE rng = :rng";
let p = params!{
"id" => id,
"rng" => given_rng_value,
};
conn.exec_drop(q, p).await?;
Ok(()) Ok(())
} }

BIN
misc/banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
misc/banner.xcf Normal file

Binary file not shown.