1
0
mirror of https://github.com/hack-chat/main.git synced 2024-03-22 13:20:33 +08:00

Merge pull request #12 from neelkamath/master

Documentation
This commit is contained in:
marzavec 2018-05-19 17:15:34 -05:00 committed by GitHub
commit 7ccbf56eeb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 124 additions and 168 deletions

View File

@ -60,4 +60,4 @@ typings/
# next.js build output
.next
config/
server/config/

46
DOCUMENTATION.md Normal file
View File

@ -0,0 +1,46 @@
You can programmatically access hack.chat using the following commands via a websocket. To prevent getting disconnected, ping the server every 50 seconds. A list of wrappers written for accessing hack.chat can be found [here](https://github.com/hack-chat/3rd-party-software-list#libraries).
The commands are to be sent through a websocket to the URL `wss://hack.chat/chat-ws` (everything sent and received are `string`s). If you are sending messages locally or to another domain, replace 'hack.chat' with the respective domain. If you're running your own instance of hack.chat, you can retain backwards-compatibility in order to ensure that software created for the main server will work on yours too.
All commands sent must be JSON objects with the command specified in the `"cmd"` key. For example:
```json
{
"cmd": "join",
"channel": "programming",
"nick": "johndoe#fag"
}
```
hack.chat has three permission levels. When you access a command, hack.chat automatically knows your permission level from your trip code. The lowest permission level is `core`. `mod` is above `core`, so it can access `core` commands in addition to `mod` commands. `admin` is similarly above `mod`.
# `core`
|Command|Parameters|Explanation|
|-------|----------|-----------|
|`changenick`|`nick`|Changes the current connection's nickname.|
|`chat`|`text`|This broadcasts `text` to the channel the user is connected to.|
|`disconnect`||An event handler or forced disconnect.|
|`invite`|`nick`|Generates a pseudo-unique channel name and passes it to both the calling user and `nick`.|
|`join`|`channel`, `nick`|Places the calling socket into the target channel with the target nick and broadcasts the event to the channel.|
|`morestats`||Sends back the current server's stats to the calling client.|
|`move`|`channel`|This will change the current channel to `channel`.|
|`stats`||Sends back legacy server stats to the calling client. Use `morestats` when possible.|
|`help`|`category` or `command`|Gives documentation programmatically. If `category` (the permission level, such as `mod`) is sent, a list of commands available to that permission level will be sent back (as a `string` and not an `array`). This list only includes what is unique to that category and not every command a user with that permission level could perform. If `command` (e.g., `chat`) is sent, a description of the command will be sent back.|
# `mod`
|Command|Parameters|Explanation|
|-------|----------|-----------|
|`ban`|`nick`|Disconnects the target nickname in the same channel as the calling socket and adds it to the rate limiter.|
|`kick`|`nick`|Silently forces target client(s) into another channel. `nick` may be `string` or `array` of `string`s.|
|`unban`|`ip` or `hash`|Removes the target ip from the rate limiter.|
# `admin`
|Command|Parameters|Explanation|
|-------|----------|-----------|
|`addmod`|`nick`|Adds the target trip to the config as a mod and upgrades the socket type.|
|`listusers`||Outputs all current channels and sockets in those channels.|
|`reload`||(Re)loads any new commands into memory and outputs errors, if any.|
|`saveconfig`||Saves the current config.|
|`shout`|`text`|Displays the passed text to each client connected.|

13
LICENSE Normal file
View File

@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

124
README.md
View File

@ -1,107 +1,51 @@
# Hack.Chat
# hack.chat
[https://hack.chat/](https://hack.chat/) is a minimal, distraction-free, account-less, log-less, disappearing chat service that is easily deployable as your own service. The client comes bundled with LaTeX rendering provided by [https://github.com/Khan/KaTeX](https://github.com/Khan/KaTeX).
[hack.chat](https://hack.chat/) is a minimal, distraction-free, accountless, logless, disappearing chat service which is easily deployable as your own service. The client comes bundled with LaTeX rendering provided by [KaTeX](https://github.com/Khan/KaTeX).
A list of software developed for the hack.chat framework can be found at: [https://github.com/hack-chat/3rd-party-software-list](https://github.com/hack-chat/3rd-party-software-list). This includes bots, clients, docker containers & more.
A list of software developed for the hack.chat framework can be found at the [3rd party software list](https://github.com/hack-chat/3rd-party-software-list) repository. This includes bots, clients, docker containers, etc.
This is a backwards compatible continuation of the work by Andrew Belt [https://github.com/AndrewBelt/hack.chat](https://github.com/AndrewBelt/hack.chat). The server code has been updated to ES6 along with several new features- including new commands and hot-reload of the commands/protocol.
This is a backwards compatible continuation of the [work by Andrew Belt](https://github.com/AndrewBelt/hack.chat). The server code has been updated to ES6 along with several new features including new commands and hot-reload of the commands/protocol. There is also [documentation](DOCUMENTATION.md) and a [changelog](CHANGELOG.md).
## Getting Started
# Installation
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.
## Prerequisites
### Prerequisites
- [node.js 8.10.0](https://nodejs.org/en/download/package-manager/#windows) or higher
The following versions are __required__:
## Installing
```
node >= 8.10.0
npm >= 5.7.1
```
1. [Clone](https://help.github.com/articles/cloning-a-repository/) the repository: `git clone https://github.com/hack-chat/main.git`
1. Change the directory: `cd main`
1. Install the dependencies: `npm install`
1. Configure: `npm start`
An installation guide for your operating system can be found at: [https://nodejs.org/en/download/package-manager/](https://nodejs.org/en/download/package-manager/)
If you change the `websocketPort` option during the config setup then these changes will need to be reflected on [line 59 of client.js](https://github.com/hack-chat/main/blob/master/client/client.js#L59).
### Installing
# Usage
First you will first need to clone this git, if you are unfamiliar with this process read [https://help.github.com/articles/cloning-a-repository/](https://help.github.com/articles/cloning-a-repository/), or to clone with git:
1. `cd` into the repository: `cd main`
1. Start the server: `npm start` with a process manager.
1. Launch: `client/index.html`
1. (OPTIONAL) If you want to deploy your hack.chat instance to a server, push everything except the `node_modules` directory and install the dependencies (`npm install`).
You can now run start the server software with a process manager like [PM2](https://github.com/Unitech/pm2) (e.g., `pm2 start server/main.js --name HackChat`). The client code will need to be copied into your http server directory. If you plan on using SSL to serve the client; you will need to use a reverse proxy, as TLS is not natively supported by the hack.chat server software (this may change in future releases).
```
git clone https://github.com/hack-chat/main.git
```
# Contributing
Once cloned, the server will need to be setup. Using your terminal run:
- If you are modifying commands, make sure it is backwards compatible with the legacy client and you update the documentation accordingly.
- Use [the template](templateCommand.js) to learn how to create new commands.
- Use two space indents.
- Name files in camelCase.
- Scripts that do not default to strict mode (such as modules) must use the `'use strict'` directive.
```
cd main/server/
npm install
```
# Credits
Or on a Windows machine with Yarn installed:
* [**Marzavec**](https://github.com/marzavec) - *Initial work*
* [**MinusGix**](https://github.com/MinusGix) - *Base updates*
* Andrew Belt, https://github.com/AndrewBelt/hack.chat, for original base work
* [wwandrew](https://github.com/wwandrew/), for finding server flaws (including attack vectors) and submitting ~~___incredibly detailed___~~ bug reports
* [Everyone else](https://github.com/hack-chat/main/graphs/contributors) who participated in this project.
```
cd main/server/
yarn install
```
# License
This will install the required packages to run hack.chat. Next the server will need to be configured, again in your terminal run:
```
node main.js
```
The configuration script will execute the initial server setup by requesting input. Follow the steps until it finishes:
```
Note: npm/yarn run config will re-run this utility.
You will now be asked for the following:
- Admin Name, the initial admin username
- Admin Pass, the initial admin password
- Port, the port for the websocket
- Salt, the salt for username trip
prompt: adminName: admin
prompt: adminPass: ****
prompt: websocketPort: (6060)
prompt: tripSalt: ************
Config generated! You may now start the server normally.
```
___Note:___ if you change the `websocketPort` option during the config setup then these changes will need to be reflected on line 64 of the [client.js](https://github.com/hack-chat/main/blob/master/client/client.js#L64).
After the config script runs, the process will exit & the server will need to be relaunched. For a production environment we recommend using [PM2](https://github.com/Unitech/pm2) to start the server:
```
cd main/server/
pm2 start main.js --name HackChat
```
[Launch the client](./client/README.md) `main/client/index.html`, you may now begin development or deploy to production environment.
## Deployment
After the initial installation and configuration, push everything except the node_modules folder to the live server and re-run:
```
npm install
```
You can now run start the server software with a process manager like [PM2](https://github.com/Unitech/pm2). The client code will need to be copied into your http server directory. If you plan on using SSL to serve the client; you will need to use a reverse proxy, as TLS is not natively supported by the hack.chat server software (this may change in future releases).
## Authors
* **Marzavec** - *Initial work* - [https://github.com/marzavec](https://github.com/marzavec)
* **MinusGix** - *Base updates* - [https://github.com/MinusGix](https://github.com/MinusGix)
See also the list of [contributors](https://github.com/hack-chat/main/graphs/contributors) who participated in this project.
## License
This project is licensed under the WTFPL License - see the [http://www.wtfpl.net/txt/copying/](http://www.wtfpl.net/txt/copying/) file for details
## Acknowledgments
* Andrew Belt, [https://github.com/AndrewBelt/hack.chat](https://github.com/AndrewBelt/hack.chat), for original base work
* wwandrew [https://github.com/wwandrew/](https://github.com/wwandrew/), for finding server flaws (including attack vectors) and submitting ~~___incredibly detailed___~~ bug reports
This project is licensed under the [WTFPL License](LICENSE).

View File

@ -36,13 +36,13 @@ function $(query) {
function localStorageGet(key) {
try {
return window.localStorage[key]
} catch(e) { }
} catch (e) { }
}
function localStorageSet(key, val) {
try {
window.localStorage[key] = val
} catch(e) { }
} catch (e) { }
}
var ws;
@ -214,10 +214,12 @@ function pushMessage(args) {
// Temporary hotfix for \rule spamming, see https://github.com/Khan/KaTeX/issues/109
textEl.innerHTML = textEl.innerHTML.replace(/\\rule|\\\\\s*\[.*?\]/g, '');
try {
renderMathInElement(textEl, {delimiters: [
{ left: "$$", right: "$$", display: true },
{ left: "$", right: "$", display: false },
]})
renderMathInElement(textEl, {
delimiters: [
{ left: "$$", right: "$$", display: true },
{ left: "$", right: "$", display: false },
]
})
} catch (e) {
console.warn(e);
}
@ -601,4 +603,4 @@ if (myChannel == '') {
$('#sidebar').classList.add('hidden');
} else {
join(myChannel);
}
}

View File

@ -393,4 +393,4 @@
}
}
}
}
}

View File

@ -2,7 +2,7 @@
"name": "hack.chat-v2",
"version": "2.0.1",
"description": "a minimal distraction free chat application",
"main": "main.js",
"main": "server/main.js",
"repository": {
"type": "git",
"url": "git+https://github.com/hack-chat/main.git"
@ -12,11 +12,10 @@
"npm": ">= 5.7.1"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js",
"config": "node src/scripts/configure.js",
"debug": "node src/scripts/debug.js",
"dev": "node src/scripts/debug.js"
"start": "node server/main.js",
"config": "node server/src/scripts/configure.js",
"debug": "node server/src/scripts/debug.js",
"dev": "node server/src/scripts/debug.js"
},
"author": "Marzavec",
"license": "WTFPL",
@ -31,4 +30,4 @@
"readdir-recursive": "0.0.4",
"ws": "^5.0.0"
}
}
}

View File

@ -1 +0,0 @@
(TODO)

View File

@ -2,8 +2,6 @@
Description: Adds the target trip to the mod list then elevates the uType
*/
'use strict';
exports.run = async (core, server, socket, data) => {
if (socket.uType != 'admin') {
// ignore if not admin

View File

@ -2,8 +2,6 @@
Description: Outputs all current channels and their user nicks
*/
'use strict';
exports.run = async (core, server, socket, data) => {
if (socket.uType != 'admin') {
// ignore if not admin

View File

@ -2,8 +2,6 @@
Description: Clears and resets the command modules, outputting any errors
*/
'use strict';
exports.run = async (core, server, socket, data) => {
if (socket.uType != 'admin') {
// ignore if not admin
@ -34,3 +32,4 @@ exports.info = {
name: 'reload',
description: '(Re)loads any new commands into memory, outputs errors if any'
};

View File

@ -2,8 +2,6 @@
Description: Writes any changes to the config to the disk
*/
'use strict';
exports.run = async (core, server, socket, data) => {
if (socket.uType != 'admin') {
// ignore if not admin

View File

@ -2,8 +2,6 @@
Description: Emmits a server-wide message as `info`
*/
'use strict';
exports.run = async (core, server, socket, data) => {
if (socket.uType != 'admin') {
// ignore if not admin
@ -22,4 +20,4 @@ exports.info = {
name: 'shout',
usage: 'shout {text}',
description: 'Displays passed text to every client connected'
};
};

View File

@ -2,8 +2,6 @@
Description: Generates a semi-unique channel name then broadcasts it to each client
*/
'use strict';
const verifyNickname = (nick) => {
return /^[a-zA-Z0-9_]{1,24}$/.test(nick);
};

View File

@ -2,8 +2,6 @@
Description: Rebroadcasts any `text` to all clients in a `channel`
*/
'use strict';
const parseText = (text) => {
if (typeof text !== 'string') {
return false;
@ -61,4 +59,4 @@ exports.info = {
name: 'chat',
usage: 'chat {text}',
description: 'Broadcasts passed `text` field to the calling users channel'
};
};

View File

@ -4,8 +4,6 @@
by a client to have the connection severed.
*/
'use strict';
exports.run = async (core, server, socket, data) => {
if (socket.channel) {
server.broadcast({
@ -20,4 +18,4 @@ exports.run = async (core, server, socket, data) => {
exports.info = {
name: 'disconnect',
description: 'Event handler or force disconnect (if your into that kind of thing)'
};
};

View File

@ -2,8 +2,6 @@
Description: Outputs the current command module list or command categories
*/
'use strict';
const stripIndents = require('common-tags').stripIndents;
exports.run = async (core, server, socket, data) => {
@ -48,4 +46,4 @@ exports.info = {
name: 'help',
usage: 'help ([ type:categories] | [category:<category name> | command:<command name> ])',
description: 'Outputs information about the servers current protocol'
};
};

View File

@ -2,8 +2,6 @@
Description: Generates a semi-unique channel name then broadcasts it to each client
*/
'use strict';
const verifyNickname = (nick) => {
return /^[a-zA-Z0-9_]{1,24}$/.test(nick);
};
@ -64,4 +62,4 @@ exports.info = {
name: 'invite',
usage: 'invite {nick}',
description: 'Generates a unique (more or less) room name and passes it to two clients'
};
};

View File

@ -2,8 +2,6 @@
Description: Initial entry point, applies `channel` and `nick` to the calling socket
*/
'use strict';
const crypto = require('crypto');
const hash = (password) => {
@ -134,4 +132,4 @@ exports.info = {
name: 'join',
usage: 'join {channel} {nick}',
description: 'Place calling socket into target channel with target nick & broadcast event to channel'
};
};

View File

@ -2,8 +2,6 @@
Description: Outputs more info than the legacy stats command
*/
'use strict';
const stripIndents = require('common-tags').stripIndents;
const formatTime = (time) => {
@ -52,4 +50,4 @@ exports.run = async (core, server, socket, data) => {
exports.info = {
name: 'morestats',
description: 'Sends back current server stats to the calling client'
};
};

View File

@ -2,8 +2,6 @@
Description: Generates a semi-unique channel name then broadcasts it to each client
*/
'use strict';
exports.run = async (core, server, socket, data) => {
if (server._police.frisk(socket.remoteAddress, 6)) {
server.reply({
@ -82,4 +80,4 @@ exports.info = {
name: 'move',
usage: 'move {channel}',
description: 'This will change the current channel to the new one provided'
};
};

View File

@ -2,8 +2,6 @@
Description: Legacy stats output, kept for compatibility, outputs user and channel count
*/
'use strict';
exports.run = async (core, server, socket, data) => {
let ips = {};
let channels = {};
@ -31,4 +29,4 @@ exports.run = async (core, server, socket, data) => {
exports.info = {
name: 'stats',
description: 'Sends back legacy server stats to the calling client'
};
};

View File

@ -2,8 +2,6 @@
Description: Adds the target socket's ip to the ratelimiter
*/
'use strict';
exports.run = async (core, server, socket, data) => {
if (socket.uType == 'user') {
// ignore if not mod or admin

View File

@ -2,8 +2,6 @@
Description: Forces a change on the target socket's channel, then broadcasts event
*/
'use strict';
exports.run = async (core, server, socket, data) => {
if (socket.uType === 'user') {
// ignore if not mod or admin
@ -77,4 +75,4 @@ exports.info = {
name: 'kick',
usage: 'kick {nick}',
description: 'Silently forces target client(s) into another channel. `nick` may be string or array of strings'
};
};

View File

@ -2,8 +2,6 @@
Description: Removes a target ip from the ratelimiter
*/
'use strict';
exports.run = async (core, server, socket, data) => {
if (socket.uType == 'user') {
// ignore if not mod or admin
@ -54,4 +52,4 @@ exports.info = {
name: 'unban',
usage: 'unban {[ip || hash]}',
description: 'Removes target ip from the ratelimiter'
};
};

View File

@ -8,15 +8,13 @@
*
*/
'use strict';
class Police {
/**
* Create a ratelimiter instance.
*/
constructor () {
this._records = {};
this._halflife = 30000; // ms
this._halflife = 30 * 1000; // milliseconds
this._threshold = 25;
this._hashes = [];
}

View File

@ -7,8 +7,6 @@
*
*/
'use strict';
const wsServer = require('ws').Server;
const socketReady = require('ws').OPEN;
const crypto = require('crypto');

View File

@ -7,8 +7,6 @@
*
*/
'use strict';
const path = require('path');
const chalk = require('chalk');
const didYouMean = require('didyoumean2');

View File

@ -8,8 +8,6 @@
*
*/
'use strict';
const stripIndents = require('common-tags').stripIndents;
const dateFormat = require('dateformat');
const chalk = require('chalk');

View File

@ -7,8 +7,6 @@
*
*/
'use strict';
const read = require('readdir-recursive');
const path = require('path');

View File

@ -7,8 +7,6 @@
*
*/
'use strict';
class Stats {
/**
* Create a stats instance.

View File

@ -2,8 +2,6 @@
Description: This is a template module that should not be on prod
*/
'use strict';
// you can require() modules here
// this function will only be only in the scope of the module
@ -50,4 +48,4 @@ exports.info = {
aliases: ['templateModule'], // optional, an array of other names this module can be executed by
usage: 'showcase {echo}', // used for help output, can be ommited if no parameters are required
description: 'Simple command module template & info' // used for help output
};
};