summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/_coverpage.md17
-rw-r--r--docs/api/README.md92
-rw-r--r--docs/api/_sidebar.md7
-rw-r--r--docs/api/hooks.md110
-rw-r--r--docs/api/objects.md (renamed from docs/README.md)93
-rw-r--r--docs/api/packets.md1
-rw-r--r--docs/api/plugin.md76
-rw-r--r--docs/index.html7
-rw-r--r--docs/user/README.md66
-rw-r--r--docs/user/_sidebar.md3
-rw-r--r--docs/user/advanced.md90
-rw-r--r--docs/user/discord.md20
-rw-r--r--docs/user/img/step1.pngbin0 -> 46232 bytes
-rw-r--r--docs/user/img/step2.pngbin0 -> 38854 bytes
-rw-r--r--docs/user/img/step3.pngbin0 -> 25723 bytes
-rw-r--r--docs/user/img/step4.pngbin0 -> 40307 bytes
-rw-r--r--docs/user/img/step5.pngbin0 -> 225097 bytes
-rw-r--r--docs/user/img/step6.pngbin0 -> 47259 bytes
18 files changed, 488 insertions, 94 deletions
diff --git a/docs/_coverpage.md b/docs/_coverpage.md
new file mode 100644
index 0000000..78ec250
--- /dev/null
+++ b/docs/_coverpage.md
@@ -0,0 +1,17 @@
+![logo](/favicon.ico)
+
+# Sakuya AC
+
+> The Perfect and Elegant YSFlight Proxy Software
+
+- Extensible, has a well documented plugin API
+- Fast, uses asyncio so that it doesn't lag
+- Completely free and open source lisenced under GPLv3
+
+Contributors
+- Skipper
+- Biry
+
+[Github](https://github.com/the-indian-dev/sakuya-ac)
+[API Documentation](/api/README.md)
+[User Documentation](/user/README.md)
diff --git a/docs/api/README.md b/docs/api/README.md
new file mode 100644
index 0000000..736c0aa
--- /dev/null
+++ b/docs/api/README.md
@@ -0,0 +1,92 @@
+# Sakuya AC API Documentation
+
+Sakuya AC : The perfect and elegant YSFlight Proxy Software. It is written in Python. Uses
+asyncio so that it doesn't lag. This documentation will guide you through creating your
+own Plugin for Sakuya AC.
+
+## Getting Started
+
+To get started with Sakuya AC, you need to have Python 3.9 or higher installed on your system.
+
+### Basic Structure of a Plugin
+
+There are two ways to work with the proxy:
+1. Hooks : These actually modify the incoming/outgoing packets from YSF Server, these are blocking
+and can be used to modify the packets.
+- Example : G Limiter, Chat Filter; As these need to modify the packets at that instant
+
+2. Commands : These are non essential and do not modify the incoming/outgong packets, you can send your
+own packets to server/client. These are non blocking.
+- Example : Fog color changer, Ban command; these do not need to modify any commands at that instant
+
+- All plugins are saved in plugins directory in the root of the project.
+
+### Simple Command Plugin
+
+```python
+"""
+This is an example test command!
+"""
+
+from lib import YSchat
+from time import sleep
+
+ENABLED = False
+
+class Plugin:
+ def __init__(self):
+ self.plugin_manager = None
+
+ def register(self, plugin_manager):
+ self.plugin_manager = plugin_manager
+ self.plugin_manager.register_command('test', self.test)
+ self.plugin_manager.register_command('timer', self.timer)
+
+ def test(self, full_message, player, message_to_client, message_to_server):
+ message_to_client.append(YSchat.message("Test command received"))
+ return True
+
+ def timer(self, full_message, player, message_to_client, message_to_server):
+ sleep(5)
+ message_to_client.append(YSchat.message("Timer ended"))
+ return True
+```
+- You start the plugin by giving it a description,
+- You must have a global ENABLED variable, which is set by the user
+ if they wish to enable the plugin or not
+- You must have a class Plugin, which has a register method
+ use ``register_command`` to register a command.
+ -- ``self.plugin_manager.register_command('command_name', self.function_name)``
+- now self.function_name must take the shown parameters
+
+### Simple Hooks Plugin
+
+```python
+"""This plugin will flash the lights/fog colour whenever a flight status update
+is sent
+It can be enabled here by changing the value of ENABLED to True."""
+from lib.PacketManager.packets import FSNETCMD_SKYCOLOR, FSNETCMD_FOGCOLOR
+from random import randint
+ENABLED = True
+
+class Plugin:
+ def __init__(self):
+ self.plugin_manager = None
+
+ def register(self, plugin_manager):
+ self.plugin_manager = plugin_manager
+ self.plugin_manager.register_hook('on_flight_data', self.on_receive)
+
+ def on_receive(self, data, player, messages_to_client, *args):
+ sky_colour_packet = FSNETCMD_SKYCOLOR.encode(randint(0, 255), randint(0, 255), randint(0, 255), True)
+ fog_colour_packet = FSNETCMD_FOGCOLOR.encode(randint(0, 255), randint(0, 255), randint(0, 255), True)
+ messages_to_client.append(sky_colour_packet)
+ messages_to_client.append(fog_colour_packet)
+ return True
+```
+- Unlike the previous example, this uses a hook which modifies the packet from the server at that instant
+- You must return True at the end of the function to indicate that the original packet will be sent
+ -- (In this case, the orginal packet is the flight data, not sending will cause the client to
+ not receive the flight data)
+- returning False, means the orginal packet which triggered the hook will not be sent to the YSF server,
+this is useful for chat filters etc.
diff --git a/docs/api/_sidebar.md b/docs/api/_sidebar.md
new file mode 100644
index 0000000..a8f77cf
--- /dev/null
+++ b/docs/api/_sidebar.md
@@ -0,0 +1,7 @@
+* [Home](/api/README.md)
+* [Plugin Structure](/api/plugin.md)
+* [Class Reference](/api/objects.md)
+ - [Aircraft](/api/objects.md#aircraft-class)
+ - [Player](/api/objects.md#player-class)
+* [Packet Reference](/api/packets.md)
+* [Hooks Reference](/api/hooks.md)
diff --git a/docs/api/hooks.md b/docs/api/hooks.md
new file mode 100644
index 0000000..373b42f
--- /dev/null
+++ b/docs/api/hooks.md
@@ -0,0 +1,110 @@
+# Introduction
+
+Hooks are blocking functions that are called when a specific event occurs.
+They are used to modify the behavior of the proxy. Every hook function
+must return a `bool` value, `True` if the packet that triggered the hook
+should be sent to the client/server or `False` if the packet should be
+dropped and not sent.
+
+# Hook Structure
+
+In main `Plugin` Class, there must be a `register` method, under which
+you must declare your hooks.
+> eg.
+> ```python
+> def register(self, plugin_manager):
+> self.plugin_manager = plugin_manager
+> self.plugin_manager.register_hook('on_flight_data', self.on_receive)
+>```
+> This will trigger the `on_receive` method of your plugin when the `on_flight_data` hook is triggered.
+
+# Hook Function Structure
+
+Every hook function must have the following structure:
+```python
+def on_receive(self, data, player, message_to_client, message_to_server)
+```
+Where:
+- `data` is the packet object that triggered the hook, It is a `bytes` object.
+The data is sent without the header.(that is the size of the packet)
+
+- `player` is the `Player` object that triggered the hook.
+
+- `message_to_client` is the list that contains the packets that will be sent to the client.
+ you must append to it and return a value for the packet to be sent.
+
+- `message_to_server` is the list that contains the packets that will be sent to the server.
+ you must append to it and return a value for the packet to be sent.
+
+> You must return a `bool` value, `True` if the packet that triggered the hook should be
+> sent to the client/server or `False` if the packet should be dropped and not sent.
+
+# Hook List
+
+## Client to Server Side
+
+| Hook | Packet Object |
+|-------------------------|-----------------------|
+| `on_login` | `FSNETCMD_LOGON` |
+| `on_logout` | `FSNETCMD_LOGOFF` |
+| `on_error` | `FSNETCMD_ERROR` |
+| `on_load_field` | `FSNETCMD_LOADFIELD` |
+| `on_add_object` | `FSNETCMD_ADDOBJECT` |
+| `on_readback` | `FSNETCMD_READBACK` |
+| `on_smoke_color` | `FSNETCMD_SMOKECOLOR` |
+| `on_join_request` | `FSNETCMD_JOINREQUEST`|
+| `on_join_approval` | `FSNETCMD_JOINAPPROVAL`|
+| `on_reject_join_request`| `FSNETCMD_REJECTJOINREQ`|
+| `on_flight_data` | `FSNETCMD_AIRPLANESTATE`|
+| `on_unjoin` | `FSNETCMD_UNJOIN` |
+| `on_remove_airplane` | `FSNETCMD_REMOVEAIRPLANE`|
+| `on_request_test_airplane`| `FSNETCMD_REQUESTTESTAIRPLANE`|
+| `on_kill_server` | `FSNETCMD_KILLSERVER` |
+| `on_prepare_simulation` | `FSNETCMD_PREPARESIMULATION`|
+| `on_test_packet` | `FSNETCMD_TESTPACKET` |
+| `on_lockon` | `FSNETCMD_LOCKON` |
+| `on_remove_ground` | `FSNETCMD_REMOVEGROUND`|
+| `on_missile_launch` | `FSNETCMD_MISSILELAUNCH`|
+| `on_get_damage` | `FSNETCMD_GETDAMAGE` |
+| `on_weapon_config` | `FSNETCMD_WEAPONCONFIG`|
+| `on_air_cmd` | `FSNETCMD_AIRCMD` |
+| `on_chat` | `FSNETCMD_TEXTMESSAGE`|
+| `on_environment` | `FSNETCMD_ENVIRONMENT`|
+| `on_sky_color` | `FSNETCMD_SKYCOLOR` |
+| `on_fog_color` | `FSNETCMD_FOGCOLOR` |
+| `on_list` | `FSNETCMD_LIST` |
+
+<br>
+
+## Server to Client Side
+
+| Hook | Packet Object |
+|-------------------------------|-----------------------|
+| `on_login_server` | `FSNETCMD_LOGON` |
+| `on_logout_server` | `FSNETCMD_LOGOFF` |
+| `on_error_server` | `FSNETCMD_ERROR` |
+| `on_load_field_server` | `FSNETCMD_LOADFIELD` |
+| `on_add_object_server` | `FSNETCMD_ADDOBJECT` |
+| `on_readback_server` | `FSNETCMD_READBACK` |
+| `on_smoke_color_server` | `FSNETCMD_SMOKECOLOR` |
+| `on_join_request_server` | `FSNETCMD_JOINREQUEST`|
+| `on_join_approval_server` | `FSNETCMD_JOINAPPROVAL`|
+| `on_reject_join_request_server`| `FSNETCMD_REJECTJOINREQ`|
+| `on_flight_data_server` | `FSNETCMD_AIRPLANESTATE`|
+| `on_unjoin_server` | `FSNETCMD_UNJOIN` |
+| `on_remove_airplane_server` | `FSNETCMD_REMOVEAIRPLANE`|
+| `on_request_test_airplane_server`| `FSNETCMD_REQUESTTESTAIRPLANE`|
+| `on_kill_server_server` | `FSNETCMD_KILLSERVER` |
+| `on_prepare_simulation_server`| `FSNETCMD_PREPARESIMULATION`|
+| `on_test_packet_server` | `FSNETCMD_TESTPACKET` |
+| `on_lockon_server` | `FSNETCMD_LOCKON` |
+| `on_remove_ground_server` | `FSNETCMD_REMOVEGROUND`|
+| `on_missile_launch_server` | `FSNETCMD_MISSILELAUNCH`|
+| `on_get_damage_server` | `FSNETCMD_GETDAMAGE` |
+| `on_weapon_config_server` | `FSNETCMD_WEAPONCONFIG`|
+| `on_air_cmd_server` | `FSNETCMD_AIRCMD` |
+| `on_chat_server` | `FSNETCMD_TEXTMESSAGE`|
+| `on_environment_server` | `FSNETCMD_ENVIRONMENT`|
+| `on_sky_color_server` | `FSNETCMD_SKYCOLOR` |
+| `on_fog_color_server` | `FSNETCMD_FOGCOLOR` |
+| `on_list_server` | `FSNETCMD_LIST` |
diff --git a/docs/README.md b/docs/api/objects.md
index 9af29ef..bdd5d49 100644
--- a/docs/README.md
+++ b/docs/api/objects.md
@@ -1,96 +1,3 @@
-# Sakuya AC API Documentation
-
-Sakuya AC : The perfect and elegant YSFlight Proxy Software. It is written in Python. Uses
-asyncio so that it doesn't lag. This documentation will guide you through creating your
-own Plugin for Sakuya AC.
-
-## Getting Started
-
-To get started with Sakuya AC, you need to have Python 3.9 or higher installed on your system.
-
-### Basic Structure of a Plugin
-
-There are two ways to work with the proxy:
-1. Hooks : These actually modify the incoming/outgoing packets from YSF Server, these are blocking
-and can be used to modify the packets.
-- Example : G Limiter, Chat Filter; As these need to modify the packets at that instant
-
-2. Commands : These are non essential and do not modify the incoming/outgong packets, you can send your
-own packets to server/client. These are non blocking.
-- Example : Fog color changer, Ban command; these do not need to modify any commands at that instant
-
-- All plugins are saved in plugins directory in the root of the project.
-
-### Simple Command Plugin
-
-```python
-"""
-This is an example test command!
-"""
-
-from lib import YSchat
-from time import sleep
-
-ENABLED = False
-
-class Plugin:
- def __init__(self):
- self.plugin_manager = None
-
- def register(self, plugin_manager):
- self.plugin_manager = plugin_manager
- self.plugin_manager.register_command('test', self.test)
- self.plugin_manager.register_command('timer', self.timer)
-
- def test(self, full_message, player, message_to_client, message_to_server):
- message_to_client.append(YSchat.message("Test command received"))
- return True
-
- def timer(self, full_message, player, message_to_client, message_to_server):
- sleep(5)
- message_to_client.append(YSchat.message("Timer ended"))
- return True
-```
-- You start the plugin by giving it a description,
-- You must have a global ENABLED variable, which is set by the user
- if they wish to enable the plugin or not
-- You must have a class Plugin, which has a register method
- use ``register_command`` to register a command.
- -- ``self.plugin_manager.register_command('command_name', self.function_name)``
-- now self.function_name must take the shown parameters
-
-### Simple Hooks Plugin
-
-```python
-"""This plugin will flash the lights/fog colour whenever a flight status update
-is sent
-It can be enabled here by changing the value of ENABLED to True."""
-from lib.PacketManager.packets import FSNETCMD_SKYCOLOR, FSNETCMD_FOGCOLOR
-from random import randint
-ENABLED = True
-
-class Plugin:
- def __init__(self):
- self.plugin_manager = None
-
- def register(self, plugin_manager):
- self.plugin_manager = plugin_manager
- self.plugin_manager.register_hook('on_flight_data', self.on_receive)
-
- def on_receive(self, data, player, messages_to_client, *args):
- sky_colour_packet = FSNETCMD_SKYCOLOR.encode(randint(0, 255), randint(0, 255), randint(0, 255), True)
- fog_colour_packet = FSNETCMD_FOGCOLOR.encode(randint(0, 255), randint(0, 255), randint(0, 255), True)
- messages_to_client.append(sky_colour_packet)
- messages_to_client.append(fog_colour_packet)
- return True
-```
-- Unlike the previous example, this uses a hook which modifies the packet from the server at that instant
-- You must return True at the end of the function to indicate that the original packet will be sent
- -- (In this case, the orginal packet is the flight data, not sending will cause the client to
- not receive the flight data)
-- returning False, means the orginal packet which triggered the hook will not be sent to the YSF server,
-this is useful for chat filters etc.
-
## Object Descriptions
### ``Aircraft`` Class
diff --git a/docs/api/packets.md b/docs/api/packets.md
new file mode 100644
index 0000000..f10c9a1
--- /dev/null
+++ b/docs/api/packets.md
@@ -0,0 +1 @@
+Incomplete!
diff --git a/docs/api/plugin.md b/docs/api/plugin.md
new file mode 100644
index 0000000..2d05ece
--- /dev/null
+++ b/docs/api/plugin.md
@@ -0,0 +1,76 @@
+# Single File Plugins
+
+These plugins are contained in a single `.py` files, recomemded for small plugins.
+
+```python
+"""
+This is an example test command!
+"""
+
+from lib import YSchat
+
+# ENABLED variable must be present in your plugin otherwise it will
+# fail to load. This is used by user to change the state of the plugin
+
+ENABLED = True
+
+class Plugin:
+ def __init__(self):
+ # Intialise the plugin here
+ self.plugin_manager = None
+
+ def register(self, plugin_manager):
+ # Here you declare functions of your plugin
+ # Bind to plugin manager
+ self.plugin_manager = plugin_manager
+ # Register your plugin commands
+ self.plugin_manager.register_command('test', self.test)
+ # Register your plugin hooks
+ self.plugin_manager.register_hook('on_flight_data', self.on_receive)
+
+ # Command Function
+ def test(self, full_message, player, message_to_client, message_to_server):
+ message_to_client.append(YSchat.message("Test command received"))
+ return True
+
+ # Hook Function
+ def on_receive(self, data, player, message_to_client, message_to_server):
+ print(f"Received flight data of {player.username}")
+ return True
+```
+
+# Multi File Plugins
+
+These plugins are contained in a directory with multiple files, recomemded for large plugins.
+
+```bash
+plugin/
+├── Plugin.py
+└── __init__.py
+```
+
+```python
+# __init__.py
+from .Plugin import Plugin
+from .Plugin import ENABLED
+```
+
+```python
+# Plugin.py
+"""
+This is a multi file plugin example
+"""
+ENABLED = True
+
+class Plugin:
+ def __init__(self):
+ self.plugin_manager = None
+
+ def register(self, plugin_manager):
+ self.plugin_manager = plugin_manager
+ self.plugin_manager.register_hook('on_flight_data', self.on_flight_data)
+
+ def on_flight_data(self, data, player,message_to_client, message_to_server):
+ print(f"Received flight data of {player.username}")
+ return True
+```
diff --git a/docs/index.html b/docs/index.html
index 551272b..f653dd2 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -15,9 +15,12 @@
<div id="app"></div>
<script>
window.$docsify = {
- name: "Sakuya AC API Documentation",
+ name: "Sakuya AC",
repo: "https://github.com/the-indian-dev/sakuya-ac",
maxLevel: 3,
+ loadSidebar: true,
+ onlyCover: true,
+ coverpage: true,
plugins: [
function (hook) {
hook.doneEach(function () {
@@ -33,5 +36,7 @@
<script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
<!-- Prism -->
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-python.min.js"></script>
+ <!-- Collapsable side bar -->
+ <script src="//cdn.jsdelivr.net/npm/docsify-sidebar-collapse/dist/docsify-sidebar-collapse.min.js"></script>
</body>
</html>
diff --git a/docs/user/README.md b/docs/user/README.md
new file mode 100644
index 0000000..8626ae1
--- /dev/null
+++ b/docs/user/README.md
@@ -0,0 +1,66 @@
+## Introduction
+
+Sakuya AC has the following features:
+1. Discord Chat sync
+2. G Limiter
+3. Plugin Support
+etc.
+
+This guide will help you to install Sakuya AC on your server
+
+## Quick Start Guide
+
+1. Clone the git repository
+```bash
+git clone [email protected]:the-indian-dev/sakuya-ac
+```
+
+2. You will need Python 3.9 or above to run Sakuya AC
+Please make sure you have correct version of Python
+
+3. Install the dependencies
+
+- For Windows
+```bash
+py -m pip install -r requirements.txt
+```
+- For Debian, Ubuntu etc.
+```bash
+sudo apt install python3-aiohttp
+```
+- For Arch Linux
+```bash
+sudo pacman -S python-aiohttp
+```
+
+4. Setup Configuration
+- Open `config.py` in a text editor
+- Start YSF Server and put its IP in `SERVER_HOST` and Port in `SERVER_PORT`.
+ The Proxy will run at the port given at `PROXY_PORT`
+
+5. Run the Proxy
+```bash
+python proxy.py
+```
+You can now connect to the Proxy server at the port you specified in `PROXY_PORT`
+
+- Advanced Configuration is documented [here](/user/advanced.md)
+
+## Installing Plugins
+
+!> Plugins can be harmful to your computer, please install from trusted sources.
+ We are NOT responsible for installing plugins from untrusted sources.
+
+1. Download plugin from a trusted source
+2. Put the plugin in the `plugins` directory
+ - If the plugin is a `.py` file, put it in the `plugins` directory
+ - If the plugin is a `.zip` file, extract it and put it in the `plugins` directory
+3. Set the `ENABLED` variable in the plugin file to `True`
+4. Run the proxy
+
+## Reporting Issues
+
+1. Please set logging level to `DEBUG` in `config.py`
+2. Please provide the replay .yfs file for the issue
+3. Provide steps to reproduce the bug
+4. Start a new issue on our Github repository.
diff --git a/docs/user/_sidebar.md b/docs/user/_sidebar.md
new file mode 100644
index 0000000..fe12b7f
--- /dev/null
+++ b/docs/user/_sidebar.md
@@ -0,0 +1,3 @@
+* [Getting Started](/user/README.md)
+* [Advanced Configuration](/user/advanced.md)
+* [Setting up Discord Chat Sync](/user/discord.md)
diff --git a/docs/user/advanced.md b/docs/user/advanced.md
new file mode 100644
index 0000000..aed5019
--- /dev/null
+++ b/docs/user/advanced.md
@@ -0,0 +1,90 @@
+# `config.py` Configuration
+
+The `config.py` file is the main configuration file for Sakuya AC. It contains the following configuration options:
+
+### `LOGGING_LEVEL`
+
+The logging level for the proxy. The logging level can be one of the following:
+1. `DEBUG` : Logs all messages (Recomedded for debugging and reporting issues)
+2. `INFO` : Logs only informational messages (Default, Recomended for normal use)
+3. `WARNING` : Logs only warning messages
+4. `CRTITICAL` : Logs only critical messages
+
+### `SERVER_HOST`
+
+The IP address of the YSF Server. The proxy will connect to this IP address.
+For local server, use `"127.0.0.1"`, It takes string values, so make sure to
+put quotaion marks around the IP address.
+
+### `SERVER_PORT`
+
+The port of the YSF Server. The proxy will connect to this port. The default is
+`7915`, which is the default port for YSF Server. It takes integer values. Do not
+put quotation marks around the port number.
+
+### `PROXY_PORT`
+
+The port on which the proxy will run. The default is `9000`. It takes integer values.
+
+### `WELCOME_MESSAGE`
+
+The welcome message that will be displayed when a client logs in to the YSFlight server.
+It takes string values. You can use the following placeholders in the message:
+- `{username}` : The username of the client
+> eg. `Welcome {username} to the server!`
+> This will display `Welcome Sakuya to the server!` when a client with username
+> `Sakuya` logs in.
+
+### `PREFIX`
+
+This is the prefix for the chat commands in your server. The default is `/`.
+It takes string values. Make sure to put quotation marks around the prefix.
+> eg. If you set the prefix to `!`, then the command to change fog color would be `!fog`
+
+!> Messages starting with prefix will be treated as commands. Make sure to set a
+ prefix that is not used in normal chat messages.
+
+### `YSF_VERSION`
+
+The version for your YSFlight server. The default is `20150425`. It takes integer values.
+
+### `G_LIM`
+
+The G-Limiter value for your server. The default is `4`. It takes integer values.
+The client will take damage if absolute value of their G force exceeds this value.
+
+- To change the interval at which the client takes G Force Damage, change the value of
+`INTERVAL` in `plugins/over_g_damage.py`. The default is `0.2`, which means the client
+takes damage every 0.2 seconds.
+
+### `HEALTH_HACK_MESSAGE`
+
+The message that will be displayed when a client tries to hack their health. It takes
+string values. The username of the client is automatically appended to the end of the
+message
+
+>eg. `HEALTH_HACK_MESSAGE = "Detected for Health Hack"`
+> This will display `Detected for Health Hack by Sakuya` when a client tries to cheat.
+
+### `SMOKE_PLANE`
+
+If the plane should smoke when it has a life lower than `SMOKE_LIFE`. The default is `True`.
+
+### `SMOKE_LIFE`
+
+The life value below which the plane should start smoking. The default is `5`. It takes integer values.
+
+### `DISCORD_ENABLED`
+
+If the Discord Chat Sync should be enabled. The default is `False`. It takes boolean values.
+You must `aiohttp` installed to use this feature.
+
+Setting up Discord Chat Sync is documented [here](/user/discord.md)
+
+### `DISCORD_TOKEN`
+
+The Discord Bot Token for the Discord Chat Sync. It takes string values.
+
+### `CHANNEL_ID`
+
+The Channel ID of the channel where the chat messages will be sent. It takes integer values.
diff --git a/docs/user/discord.md b/docs/user/discord.md
new file mode 100644
index 0000000..b6ea279
--- /dev/null
+++ b/docs/user/discord.md
@@ -0,0 +1,20 @@
+# Creating a Discord Bot account
+
+1. Go to [Discord Developer Portal](https://discord.com/developers/applications),
+ and login with your Discord account.
+2. Click on `New Application` and give your bot a name.
+ ![Step 1](img/step1.png)
+3. Go to the left sidebar and click on `Bot`.
+ ![Step 2](img/step3.png)
+4. Click on `Reset Token` and copy the token. This your bot token for `DISCORD_TOKEN` in `config.py`.
+ ![Step 3](img/step4.png)
+5. Scroll down to `Privileged Gateway Intents`.
+6. Enable **Message Content** Intent. This is important!
+ ![Step 4](img/step5.png)
+
+# Getting Channel ID
+
+1. Go to your Discord server and right click on the channel where you want to sync the chat.
+2. Click on `Copy ID` to copy the channel ID.
+ ![Step 5](img/step6.png)
+3. Paste the channel ID in `CHANNEL_ID` in `config.py`.
diff --git a/docs/user/img/step1.png b/docs/user/img/step1.png
new file mode 100644
index 0000000..e7b2447
--- /dev/null
+++ b/docs/user/img/step1.png
Binary files differ
diff --git a/docs/user/img/step2.png b/docs/user/img/step2.png
new file mode 100644
index 0000000..3eee04e
--- /dev/null
+++ b/docs/user/img/step2.png
Binary files differ
diff --git a/docs/user/img/step3.png b/docs/user/img/step3.png
new file mode 100644
index 0000000..165f711
--- /dev/null
+++ b/docs/user/img/step3.png
Binary files differ
diff --git a/docs/user/img/step4.png b/docs/user/img/step4.png
new file mode 100644
index 0000000..0fd4edd
--- /dev/null
+++ b/docs/user/img/step4.png
Binary files differ
diff --git a/docs/user/img/step5.png b/docs/user/img/step5.png
new file mode 100644
index 0000000..69fdf8a
--- /dev/null
+++ b/docs/user/img/step5.png
Binary files differ
diff --git a/docs/user/img/step6.png b/docs/user/img/step6.png
new file mode 100644
index 0000000..f7f847f
--- /dev/null
+++ b/docs/user/img/step6.png
Binary files differ