From c1259e69cb7f5dc038c3db801113d4108847a417 Mon Sep 17 00:00:00 2001
From: slatinsky
Date: Wed, 2 Aug 2023 01:26:08 +0200
Subject: [PATCH] documentation revamp
---
README.md | 238 ++++++++++++++++++-----------
docs/Supporting-other-exporters.md | 5 +
docs/dce-export-more.png | Bin 42900 -> 58948 bytes
3 files changed, 153 insertions(+), 90 deletions(-)
diff --git a/README.md b/README.md
index c116396..47c67b1 100644
--- a/README.md
+++ b/README.md
@@ -1,59 +1,28 @@

# DiscordChatExporter-frontend (DCEF)
-View your JSON [DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter) exports as if you were using Discord interface. Also supports other exporters like [Roachbones/discordless](https://github.com/Roachbones/discordless) exporting in the same JSON format as DiscordChatExporter.
-## Why JSON exports are better than HTML exports?
-- better-suited for long-term preservation
-- contain more information than HTML exports
-- readable by third-party applications like this one or [chat-analytics](https://github.com/mlomb/chat-analytics), not just browsers
-- smaller in size
+Browse your [Discord chat exports](https://github.com/Tyrrrz/DiscordChatExporter) in a familiar discord like user interface. [Try a demo in your browser :)](https://dcef.slada.sk/).
-This project aims to provide you with better experience than what you get by just opening HTML exports in your browser. In one place and with many more features, like search, message deduplication, etc. And it will get even better in the future :).
+> Want to chat? Join [Tyrrrz's discord server](https://discord.gg/2SUWKFnHSm). I usually hang out in `#dce-frontend` channel
-## Features
-- View JSON exports in Discord like interface
-- Message deduplication - merge multiple JSON exports and view them as one
-- Lazy loaded virtual list - load only messages you need to see
-- Forums and threads support
-- Search with filters and autocomplete
-- Load assets locally or from Discord servers
-- Private messages or guild exports are supported
-- Discord Markdown rendering
-- Right click message and select "Open in discord" to view message in Discord
-- Windows and Linux support
+## Downloads
+[Windows (stable binary release)](https://github.com/slatinsky/DiscordChatExporter-frontend/releases)
-### System requirements
-- You need 1.5+ GB of free RAM for the mongodb database to work correctly
-- The browser viewer has almost no requirements, but it's recommended to have at least 1 GB of free RAM
-- Chromium based browsers and Firefox are supported, but most of the testing was done on Chromium.
-- Small viewports (mobile phones) are not supported yet
-
-Note: Discord servers are known internally as guilds
+[Linux (docker image)](https://hub.docker.com/r/slada/dcef)
## Quick start (Windows)
-Using prebuilt binaries is the easiest way to use this tool on Windows.
-
-if you don't have any exports yet, you can try out the viewer with example exports included in the release. Just skip step 3.
1. Download the latest release from [releases page](https://github.com/slatinsky/DiscordChatExporter-frontend/releases)
2. Extract the archive
-3. Move your [DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter) exports to `/exports/` folder ([supported exports](#supported-exports)). Folder structure inside this folder doesn't matter, script will find everything it needs.
+3. Move your [DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter) JSON exports to `/exports/` folder ([supported exports](#supported-exports)).
4. Run `dcef.exe`
-**Important:** files in exports folder may exceed Windows path length limit of 260 characters. If you have any issues with loading your assets you can choose one of the following solutions:
-- move your exports to a folder with shorter path
-- or run `registry_tweaks/change_260_character_path_limit_to_32767.reg` to increase the limit to 32767 characters (requires admin privileges) and restart your computer
+## Quick start (Linux)
-### Beta builds (Windows)
-If you want to try out the latest features, you can use [beta builds](https://github.com/slatinsky/DiscordChatExporter-frontend/actions/workflows/windows-build.yml). They are automatically built from the latest commit on `master` branch or from pull requests.
-
-## Docker (cross-platform)
-**Info**: Tested on Ubuntu 22.04 and WSL2 on Windows 10. **Not** tested on arm based systems like Raspberry Pi or Apple M1.
-
-This verion is the best way to [host the viewer on a server](docs/Server-hosting.md) for others to use.
+Docker version is the best way to [host the viewer on a server](docs/Server-hosting.md) for others to use.
1. pull the image from docker hub
@@ -69,95 +38,178 @@ cd /path/to/your/exports
3. Run the container
```bash
-docker run --volume "$(pwd):/dcef/exports" --volume dcef_cache:/dcef/cache --rm --name dcef -p 21011:21011 -it slada/dcef:main
+docker run --restart=always --volume "$(pwd):/dcef/exports" --volume dcef_cache:/dcef/cache --rm --name dcef -p 21011:21011 -it slada/dcef:main
```
4. Open `http://127.0.0.1:21011/` in your browser
+**Note:** arm based systems like Raspberry Pi or Apple M1 are not officially supported. Pull requests are welcome :)
-Build docker image from source code
-
-You need docker and git installed. Tested on non-snap version of docker on Ubuntu 22.04.
-1. Build image
+## Other ways to run DCEF
+
+Windows beta builds
+
+If you want to try out the latest features, you can use [beta builds](https://github.com/slatinsky/DiscordChatExporter-frontend/actions/workflows/windows-build.yml). They are automatically built from the latest commit on `main` branch. You need to be logged in to Github account to download them.
+
+
+
+Build docker image from source code
+
+You need docker and git installed. Then run:
```bash
git clone https://github.com/slatinsky/DiscordChatExporter-frontend
cd DiscordChatExporter-frontend
docker build -t dcef .
```
-Then use the same instructions as for the docker hub version, but replace `slada/dcef:main` with `dcef` in step 3.
-
+Then use the same instructions as for the Linux docker version, but replace in commands `slada/dcef:main` with `dcef`.
+
-Debugging containers
-
-To debug a running container, run `docker exec -it $(docker ps | grep 'dcef' | awk '{ print $1 }') sh`. This will open a shell inside the container.
+## Upgrade guide
-To remove volume `dcef_cache` with temporary files, run `docker volume rm dcef_cache`
+Upgrade windows binary release
-
-
-
-## Upgrade guide (Windows)
Want to upgrade from previous version? Follow these steps:
1. Download the latest release from [releases page](https://github.com/slatinsky/DiscordChatExporter-frontend/releases).
2. Delete everything (except `exports` folder) in your discordchatexporter-frontend folder.
3. Move everything (except `exports` folder) from the new release to your discordchatexporter-frontend folder.
-Info: since release 1.10.0, exports folder was changed from `/static/input/` to `/exports/`.
+
+Upgrade docker image
-## Upgrade guide (Docker)
-
-Stop the container and clear the cache volume by running `docker volume rm dcef_cache`. Then pull the latest version from git (`git pull`) and build the image again using linux instructions.
-
-
-
-## Which exports are supported?
-
-Exports are done by [DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter).
-
-- JSON export format (`--format Json`) is required
-- Including assets (`--media --reuse-media`) is highly recommended, but not required
-- Skipping markdown prerendering (`--markdown false`) is highly recommended, but not required
-- Don't forget to export **threads and forums**, because they **are not included in the main export** (see examples below for a guide on how to export them)
-
-CLI examples
-
-
-Export all accessible channels from guild:
-```
-DiscordChatExporter.Cli.exe exportguild --token DISCORD_TOKEN -g GUILD_ID --media --reuse-media --markdown false --format Json --output OUTPUT_FOLDER_PATH
-```
-Export all dms (sadly, exporting dms can't be done without selfboting):
-```
-DiscordChatExporter.Cli.exe exportdm --token DISCORD_TOKEN --media --reuse-media --markdown false --format Json --output OUTPUT_FOLDER_PATH
-```
-Export channel/thread/forum posts:
-```
-DiscordChatExporter.Cli export --token DISCORD_TOKEN --media --reuse-media --markdown false --output OUTPUT_FOLDER_PATH --format Json --channel CHANNEL_OR_THREAD_ID_OR_FORUM_POST_ID_1 CHANNEL_OR_THREAD_ID_OR_FORUM_POST_ID_2 CHANNEL_OR_THREAD_ID_OR_FORUM_POST_ID_3 CHANNEL_OR_THREAD_ID_OR_FORUM_POST_ID_4
+```bash
+cd path/to/your/exports/
+docker rm dcef --force
+docker image rm slada/dcef:main
+docker pull slada/dcef:main
+docker run --restart=always --volume "$(pwd):/dcef/exports" --volume dcef_cache:/dcef/cache --rm --name dcef -p 21011:21011 -it slada/dcef:main
+```
+
+
+
+## Uninstall
+
+Windows (binary release)
+
+DCEF does not create any files outside of its folder, so you can just delete the folder to uninstall it.
+
+Move your `exports` folder somewhere else if you want to keep your exports.
+
+
+
+Linux (docker)
+
+1. kill and delete the container
+
+```bash
+docker rm dcef --force
+```
+
+2. remove the volume
+
+```bash
+docker volume rm dcef_cache
+```
+
+3. remove the image
+
+```bash
+docker image rm slada/dcef:main
```
-
-[Helper script to export archived threads in a channel](docs/Exporting-threads.md)
+
+## How to export data from Discord to view it in DCEF?
-[Helper script to export forum posts in a channel](docs/Exporting-threads.md)
+JSON exports are created using [DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter).
-### Settings for GUI version of DiscordChatExporter
-Make sure that export format is set to `JSON`. Optionally, you can enable `Download assets` option to download images, videos and other types of assets.
+Partial export using GUI version of DiscordChatExporter
+
+Make sure that export format is set to `JSON` and `Format markdown` is disabled. Optionally, you should also enable `Download assets`+`Reuse assets` option to download images, videos and other types of assets.

**NOTE**: You can't export threads and forums using GUI version of DCE. You need to use CLI version for that.
-## Development
+
+
+
+
+Full guild export using CLI version of DiscordChatExporter
+
+> - JSON export format (`--format Json`) is required
+> - Downloading assets (`--media --reuse-media`) is highly recommended, but not required
+> - Skipping markdown prerendering (`--markdown false`) is highly recommended, but not required
+
+Export all accessible channels in a guild (**without threads and forum posts**):
+```bash
+DiscordChatExporter.Cli.exe exportguild --token DISCORD_TOKEN -g GUILD_ID --media --reuse-media --markdown false --format Json --output OUTPUT_FOLDER_PATH
+```
+
+Export threads/forum posts (you can pass multiple thread/forum post ids):
+```bash
+DiscordChatExporter.Cli export --token DISCORD_TOKEN --media --reuse-media --markdown false --output OUTPUT_FOLDER_PATH --format Json --channel THREAD_ID_OR_FORUM_POST_ID_1 THREAD_ID_OR_FORUM_POST_ID_2 THREAD_ID_OR_FORUM_POST_ID_3 THREAD_ID_OR_FORUM_POST_ID_4
+```
+
+Don't want to manually right click all threads/forums post and copy their ids? These helper scripts can help you:
+
+[Helper script to export archived threads in a channel](docs/Exporting-threads.md)
+
+[Helper script to export forum posts in a channel](docs/Exporting-threads.md)
+
+
+
+
+
+Export private messages using CLI version of DiscordChatExporter
+
+Export all dms (sadly, exporting dms can't be done without selfboting):
+```bash
+DiscordChatExporter.Cli.exe exportdm --token DISCORD_TOKEN --media --reuse-media --markdown false --format Json --output OUTPUT_FOLDER_PATH
+```
+
+
+
+
+
+
+
+## FAQ
+
+Some assets are not showing on Windows
+
+Files in `/exports/` folder may exceed Windows path length limit of 260 characters. If you have any issues with loading your assets you can choose one of the following solutions:
+- move DCEF to a folder with shorter path
+- or run `registry_tweaks/change_260_character_path_limit_to_32767.reg` to increase the limit to 32767 characters (requires admin privileges) and restart your computer. To revert this change, run `registry_tweaks/restore_260_character_path_limit.reg` and restart your computer.
+
+
+
+
+DCEF hangs and prints `Slow SessionWorkflow loop` to the console
+
+`Slow SessionWorkflow loop` messages are completely normal - if you see them, you know that data is pushed to mongodb database and the process is not stuck. Just be patient and wait for the process to finish. If you have a lot of exports, it may take a while.
+
+DCEF is not just an simple viewer. This process enriches your exports with additional data and stores them in a database for search and other features to work.
+
+
+
+
+DCEF won't run on M1 mac
+
+[This pull request](https://github.com/slatinsky/DiscordChatExporter-frontend/pull/30) may help you
+
+
+
+
+## For developers
[Architecture choices](docs/Architecture.md)
@@ -174,6 +226,11 @@ Make sure that export format is set to `JSON`. Optionally, you can enable `Downl
And for other technologies used in this project - sveltekit, docker, nodejs, nvm, pyinstaller, nginx, mongodb
+## Related projects
+
+- [Roachbones/discordless](https://github.com/Roachbones/discordless) - real time man-in-the-middle exporter
+- [mlomb/chat-analytics](https://github.com/mlomb/chat-analytics) - analytics for your Discord chats.
+
## License
GNU GENERAL PUBLIC LICENSE. See [LICENSE](LICENSE) for more details.
@@ -183,6 +240,7 @@ DiscordChatExporter-frontend is not affiliated with Discord. Discord is a regist
## Contributing
Feel free to open issues and pull requests.
+
### Short guide, how to contribute
- Fork the repository
- Create a new branch
diff --git a/docs/Supporting-other-exporters.md b/docs/Supporting-other-exporters.md
index 97be3ad..eb77911 100644
--- a/docs/Supporting-other-exporters.md
+++ b/docs/Supporting-other-exporters.md
@@ -1,3 +1,8 @@
# Supporting other exporters
+Any exporter exporting in the same format as [DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter) does, should work with this viewer. One of them is [Roachbones/discordless](https://github.com/Roachbones/discordless) - real time man-in-the-middle exporter.
+
+
+## For developers
+
Are you creating a new discord exporter and want to view the exported data with this viewer? Just convert the data from your format to the same format as DiscordChatExporter uses :).
\ No newline at end of file
diff --git a/docs/dce-export-more.png b/docs/dce-export-more.png
index 7cfd4f2348def13b9827852bbfdb34417132a65d..a5b6707a5c086cc609ae5dba6de7bc08b6449ae8 100644
GIT binary patch
literal 58948
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