mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-07-07 14:44:39 +02:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e6f9a364e1 | |||
| 0f6841593f | |||
| 2262d0abfb | |||
| ab535233dc | |||
| dcaceaddaf | |||
| 2a787d2749 | |||
| 481ddc4cd5 | |||
| c493518eaf | |||
| 450866d1f5 | |||
| 60c8703e78 | |||
| 1c343b75f8 | |||
| b2a22ab2a9 | |||
| b2ac5d8b45 | |||
| 008c2e64aa | |||
| 576ee73bfc | |||
| db1da5545a | |||
| 5397b0db7d | |||
| e89701e3f9 | |||
| a46bf9bf11 | |||
| 8dc024d244 | |||
| 9a125db0ea | |||
| d9c35f4405 | |||
| 5846129cc6 | |||
| 6f5f747632 | |||
| 6a71c59b6d | |||
| 73574ade48 | |||
| 743db67f91 | |||
| 5d7a74eece | |||
| 129df42de4 | |||
| 6508455f3a | |||
| 50b26c557f | |||
| b709fc0f15 | |||
| c118a0bb94 | |||
| 1418bec0c7 | |||
| 750fd69a50 | |||
| b1297bb7df | |||
| 3189111a0e | |||
| 6ec2c04aa3 | |||
| 7c014bf64d | |||
| c875f8f4f0 | |||
| 69e2c337d8 | |||
| 77c770acdd |
+8
-11
@@ -2,7 +2,8 @@
|
||||
|
||||
Docker distribution of DiscordChatExporter provides a way to run the app in a virtualized and isolated environment. Due to the nature of Docker, you also don't need to install any prerequisites otherwise required by DCE.
|
||||
|
||||
Note that only the CLI flavor of DiscordChatExporter is available for use with Docker.
|
||||
> **Note**:
|
||||
> Only the CLI flavor of DiscordChatExporter is available for use with Docker.
|
||||
|
||||
## Pulling
|
||||
|
||||
@@ -14,9 +15,9 @@ docker pull tyrrrz/discordchatexporter:stable
|
||||
|
||||
Note the `:stable` tag. DiscordChatExporter images are tagged according to the following patterns:
|
||||
|
||||
- `stable`: Latest stable version release and maps to the latest GitHub release. This tag is updated with release of each new version. Recommended for personal use.
|
||||
- `latest`: Built from the latest commit and maps to the latest CI build on GitHub. This tag is updated with each new commit to `master` branch. Not recommended for everyday use, but you can use it if you want to try out some features that haven't been officially released yet.
|
||||
- `x.y.z` (e.g. `2.30.1`): Fixed version release and maps to the corresponding tag on GitHub. This tag is never updated once that version has been released. Recommended for use in automation scenarios.
|
||||
- `stable` — latest stable version release. This tag is updated with each release of a new project version. Recommended for personal use.
|
||||
- `x.y.z` (e.g. `2.30.1`) — specific stable version release. This tag is pushed when the corresponding version is released and never updated thereafter. Recommended for use in automation scenarios.
|
||||
- `latest` — latest (potentially unstable) build. This tag is updated with each new commit to the `master` branch. Not recommended, unless you want to test a new feature that has not been released in a stable version yet.
|
||||
|
||||
You can see all available tags [here](https://hub.docker.com/r/tyrrrz/discordchatexporter/tags?ordering=name).
|
||||
|
||||
@@ -34,13 +35,13 @@ To export a channel:
|
||||
docker run --rm -v /path/on/machine:/out tyrrrz/discordchatexporter:stable export -t TOKEN -c CHANNELID
|
||||
```
|
||||
|
||||
If you want colored output and real-time progress reporting, pass the `-it` (interactive) option:
|
||||
If you want colored output and real-time progress reporting, pass the `-it` (interactive + pseudo-terminal) option:
|
||||
|
||||
```console
|
||||
docker run --rm -it -v /path/on/machine:/out tyrrrz/discordchatexporter:stable export -t TOKEN -c CHANNELID
|
||||
```
|
||||
|
||||
Note the `-v /path/on/machine:/out` option, which instructs Docker to bind the `/out` directory inside the container to a path on your host machine. Replace `/path/on/machine` with the directory you want the files to be saved at.
|
||||
The `-v /path/on/machine:/out` option instructs Docker to bind the `/out` directory inside the container to a path on your host machine. Replace `/path/on/machine` with the directory you want the files to be saved at.
|
||||
|
||||
> **Note**:
|
||||
> If you are running SELinux, you will need to add the `:z` option after `/out`, e.g.:
|
||||
@@ -58,14 +59,10 @@ You can also use the current working directory as the output directory by specif
|
||||
|
||||
For more information, please refer to the [Dockerfile](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/DiscordChatExporter.Cli.dockerfile) and [Docker documentation](https://docs.docker.com/engine/reference/run).
|
||||
|
||||
To get your Token and Channel IDs, please refer to [this page](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md).
|
||||
To get your Token and Channel IDs, please refer to [this page](Token-and-IDs.md).
|
||||
|
||||
## Environment variables
|
||||
|
||||
DiscordChatExpoter CLI accepts the `DISCORD_TOKEN` environment variable as a fallback for the `--token` option. You can set this variable either with the `--env` Docker option or with a combination of the `--env-file` Docker option and a `.env` file.
|
||||
|
||||
Please refer to the [Docker documentation](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file) for more information.
|
||||
|
||||
## Permission issues with Linux hosts
|
||||
|
||||
When bounding volumes between the container and the host, files mirrored from the Docker container will be owned by the Docker user (in most setups this is `root`). Please refer to this [issue comment](https://github.com/Tyrrrz/DiscordChatExporter/issues/800#issuecomment-1030471970) for instructions on how to override this behavior.
|
||||
|
||||
+23
-39
@@ -1,42 +1,36 @@
|
||||
# Install .NET runtime
|
||||
|
||||
**.NET v7.0 Runtime** is required by **DiscordChatExporter v2.37 and newer**.
|
||||
**.NET 8.0 Runtime** is required by **DiscordChatExporter**.
|
||||
|
||||
If you are using GUI flavor of DiscordChatExporter, the runtime will be installed automatically (since v2.27.1).
|
||||
If you are using the CLI from Docker, installing the runtime on the host machine is not needed.
|
||||
> **Note**:
|
||||
> Installing the **.NET Runtime** is not required if you running **DiscordChatExporter** using [Docker](Docker.md).
|
||||
|
||||
- Install
|
||||
- [Windows and macOS](#windows-and-macos)
|
||||
- [Linux](#linux)
|
||||
- [Docker](#docker)
|
||||
- [Verify installation](#verify-installation-optional)
|
||||
## Windows
|
||||
|
||||
## Windows and macOS
|
||||
Both the GUI and the CLI flavors of **DiscordChatExporter** for Windows come with a bootstrapper that should automatically install all the required prerequisites. Simply run the application and follow the presented instructions.
|
||||
|
||||
**Download directly from one of the links:**
|
||||
If, for some reason, you need to install the runtime manually, use one of the download links below:
|
||||
|
||||
- [.NET v7.0 Runtime for **Windows x64**](https://dotnet.microsoft.com/download/dotnet/thank-you/runtime-desktop-7.0.11-windows-x64-installer)
|
||||
- [.NET v7.0 Runtime for **Windows x86**](https://dotnet.microsoft.com/download/dotnet/thank-you/runtime-desktop-7.0.11-windows-x86-installer)
|
||||
- [.NET v7.0 Runtime for **Macs with Apple silicon**](https://dotnet.microsoft.com/download/dotnet/thank-you/runtime-7.0.11-macos-arm64-installer)
|
||||
- [.NET v7.0 Runtime for **Macs with an Intel processor**](https://dotnet.microsoft.com/download/dotnet/thank-you/runtime-7.0.11-macos-x64-installer)
|
||||
- [.NET 8.0 Runtime for **Windows x64**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.0-windows-x86-installer)
|
||||
- [.NET 8.0 Runtime for **Windows x86**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.0-windows-x64-installer)
|
||||
- [.NET 8.0 Runtime for **Windows arm64**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.0-windows-arm64-installer)
|
||||
|
||||
> **Note**:
|
||||
> [How can I tell if my computer is running a 32-bit (x86) or a 64-bit (x64) version of Windows?](https://support.microsoft.com/help/15056/windows-32-64-bit-faq)
|
||||
|
||||
## macOS
|
||||
|
||||
Use one of the download links below:
|
||||
|
||||
- [.NET 8.0 Runtime for **macOS x64**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.0-macos-x64-installer)
|
||||
- [.NET 8.0 Runtime for **macOS arm64**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.0-macos-arm64-installer)
|
||||
|
||||
> **Note**:
|
||||
> [Is my Mac using an Intel processor or Apple silicon?](https://support.apple.com/HT211814)
|
||||
|
||||
**Otherwise:**
|
||||
[Check out the latest version on this page](https://dotnet.microsoft.com/download/dotnet/7.0).
|
||||
Look for the download link in the '**.NET Runtime**' section, under **Installers**:
|
||||
|
||||
[](https://dotnet.microsoft.com/download/dotnet/7.0)
|
||||
> [Is my Mac using an Intel processor (x64) or Apple Silicon (arm64)?](https://support.apple.com/HT211814)
|
||||
|
||||
## Linux
|
||||
|
||||
Installing the .NET Runtime works differently depending on which Linux distribution you use.
|
||||
|
||||
Check out the instructions for your distro:
|
||||
Installing the .NET Runtime works differently depending on which Linux distribution you use. Check out the instructions for your distro:
|
||||
|
||||
- [Ubuntu](https://docs.microsoft.com/dotnet/core/install/linux-ubuntu)
|
||||
- [Debian](https://docs.microsoft.com/dotnet/core/install/linux-debian)
|
||||
@@ -44,25 +38,15 @@ Check out the instructions for your distro:
|
||||
|
||||
For other distros, please check the _'Install on Linux'_ menu on the left of [this page](https://docs.microsoft.com/dotnet/core/install/linux).
|
||||
|
||||
## Docker
|
||||
|
||||
Installing the .NET Runtime is not needed. Please refer to the [Docker usage instructions](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Docker.md) page for more information.
|
||||
|
||||
## Verify installation (optional)
|
||||
|
||||
You can check which version of **.NET Runtime** is installed by following these instructions:
|
||||
You can check which version of **.NET Runtime** is installed by running the following command in a terminal:
|
||||
|
||||
### Step 1
|
||||
```console
|
||||
dotnet --info
|
||||
```
|
||||
|
||||
**Windows:** Open Command Prompt (aka `cmd`)
|
||||
|
||||
**macOS and Linux:** Open `Terminal`
|
||||
|
||||
### Step 2
|
||||
|
||||
Run `dotnet --info`
|
||||
|
||||
If the **.NET Runtime** is correctly installed, the command will output the following:
|
||||
If the **.NET Runtime** is correctly installed, the command will output something similar to the following:
|
||||
|
||||
```console
|
||||
.NET runtimes installed:
|
||||
|
||||
@@ -2,15 +2,16 @@
|
||||
|
||||
Welcome to the getting started page!
|
||||
Here you'll learn how to use every **DiscordChatExporter** (DCE for short) feature.
|
||||
For other things you can do with DCE, check out the [Guides](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Readme.md#Guides) section.
|
||||
For other things you can do with DCE, check out the [Guides](Readme.md#guides) section.
|
||||
|
||||
If you still have unanswered questions after reading this page or if you have encountered a problem, please visit our [FAQ & Troubleshooting](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Troubleshooting.md) section.
|
||||
If you still have unanswered questions after reading this page or if you have encountered a problem, please visit our [FAQ & Troubleshooting](Troubleshooting.md) section.
|
||||
|
||||
The information presented on this page is valid for **all** platforms.
|
||||
|
||||
## GUI or CLI?
|
||||
|
||||

|
||||
|
||||
**DCE** has two different versions:
|
||||
|
||||
- **Graphical User Interface** (**GUI**) - it's the preferred version for newcomers as it is easy to use.
|
||||
@@ -19,12 +20,12 @@ The information presented on this page is valid for **all** platforms.
|
||||
You can get it by [downloading](https://github.com/Tyrrrz/DiscordChatExporter/releases/latest) the `DiscordChatExporter.CLI.zip` file.
|
||||
|
||||
If you're not comfortable with **Windows'** Command-line (cmd), please choose the GUI.
|
||||
[**macOS**](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/MacOS.md), [**Linux**](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Linux.md) and [**Docker**](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Docker.md) users can only use the CLI version.
|
||||
[**macOS**](MacOS.md), [**Linux**](Linux.md) and [**Docker**](Docker.md) users can only use the CLI version.
|
||||
|
||||
There are dedicated guides for each version:
|
||||
|
||||
- [Using the GUI](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-GUI.md)
|
||||
- [Using the CLI](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md)
|
||||
- [Using the GUI](Using-the-GUI.md)
|
||||
- [Using the CLI](Using-the-CLI.md)
|
||||
|
||||
## File formats
|
||||
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@
|
||||
|
||||
## Installing .NET Runtime
|
||||
|
||||
Please follow the [instructions provided here](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Dotnet.md).
|
||||
Please follow the [instructions provided here](Dotnet.md).
|
||||
|
||||
## Downloading and using DiscordChatExporter.Cli
|
||||
|
||||
@@ -21,6 +21,6 @@ If the above command throws a "Permission denied" error, execute this command to
|
||||
chmod 644 *.dll DiscordChatExporter.*
|
||||
```
|
||||
|
||||
> [How to get Token and Channel IDs](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md).
|
||||
> [How to get Token and Channel IDs](Token-and-IDs.md).
|
||||
|
||||
There's much more you can do with DCE.CLI! Read the [CLI explained](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#dcecli-commands-) page to get started.
|
||||
There's much more you can do with DCE.CLI! Read the [CLI explained](Using-the-CLI.md) page to get started.
|
||||
|
||||
+3
-3
@@ -4,7 +4,7 @@
|
||||
|
||||
## Installing .NET Runtime
|
||||
|
||||
Please follow the [instructions provided here](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Dotnet.md).
|
||||
Please follow the [instructions provided here](Dotnet.md).
|
||||
|
||||
## Downloading and using DiscordChatExporter.Cli
|
||||
|
||||
@@ -17,6 +17,6 @@ Please follow the [instructions provided here](https://github.com/Tyrrrz/Discord
|
||||
dotnet DiscordChatExporter.Cli.dll export -t TOKEN -c CHANNEL
|
||||
```
|
||||
|
||||
> [How to get Token and Channel IDs](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md).
|
||||
> [How to get Token and Channel IDs](Token-and-IDs.md).
|
||||
|
||||
There's much more you can do with DCE.CLI! Read the [CLI explained](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#dcecli-commands-) page to get started.
|
||||
There's much more you can do with DCE.CLI! Read the [CLI explained](Using-the-CLI.md) page to get started.
|
||||
|
||||
+16
-16
@@ -2,21 +2,21 @@
|
||||
|
||||
## Installation & Usage
|
||||
|
||||
- [Get .NET Core Runtime](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Dotnet.md) (Required for CLI; Installed automatically for GUI; Not required in Docker)
|
||||
- [Windows](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#gui-or-cli) | [macOS](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/MacOS.md) | [Linux](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Linux.md) | [Docker](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Docker.md)
|
||||
- [Get .NET Core Runtime](Dotnet.md) (Required for CLI; Installed automatically for GUI; Not required in Docker)
|
||||
- [Windows](Getting-started.md#gui-or-cli) | [macOS](MacOS.md) | [Linux](Linux.md) | [Docker](Docker.md)
|
||||
- Getting started:
|
||||
- [Using the GUI](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#using-the-gui)
|
||||
- [Using the CLI](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#using-the-cli)
|
||||
- [File formats](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#file-formats)
|
||||
- [Using the GUI](Using-the-CLI.md)
|
||||
- [Using the CLI](Using-the-CLI.md)
|
||||
- [File formats](Getting-started.md#file-formats)
|
||||
|
||||
## Guides
|
||||
|
||||
- [How to get Token and Channel IDs](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md)
|
||||
- [How to use message filters](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Message-filters.md)
|
||||
- [How to get Token and Channel IDs](Token-and-IDs.md)
|
||||
- [How to use message filters](Message-filters.md)
|
||||
- Export scheduling with CLI:
|
||||
- [Windows](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Scheduling-Windows.md)
|
||||
- [macOS](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Scheduling-MacOS.md)
|
||||
- [Linux](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Scheduling-Linux.md)
|
||||
- [Windows](Scheduling-Windows.md)
|
||||
- [macOS](Scheduling-MacOS.md)
|
||||
- [Linux](Scheduling-Linux.md)
|
||||
|
||||
## Video tutorial
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
|
||||
## FAQ & Troubleshooting
|
||||
|
||||
- [General questions](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Troubleshooting.md#general)
|
||||
- [First steps help](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Troubleshooting.md#first-steps)
|
||||
- [It's crashing/failing](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Troubleshooting.md#DCE-is-crashingfailing)
|
||||
- [.NET Core Runtime is required](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Troubleshooting.md#net-core-runtime-is-required)
|
||||
- [Errors](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Troubleshooting.md#errors)
|
||||
- [**More help**](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Troubleshooting.md)
|
||||
- [General questions](Troubleshooting.md#general)
|
||||
- [First steps help](Troubleshooting.md#first-steps)
|
||||
- [It's crashing/failing](Troubleshooting.md#DCE-is-crashingfailing)
|
||||
- [.NET Core Runtime is required](Troubleshooting.md#net-core-runtime-is-required)
|
||||
- [Errors](Troubleshooting.md#errors)
|
||||
- [**More help**](Troubleshooting.md)
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
# Scheduling exports with Cron
|
||||
|
||||
Make sure you already have **DiscordChatExporter.CLI** and **.NET Core** properly installed ([instructions here](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Linux.md)).
|
||||
Make sure you already have **DiscordChatExporter.CLI** and **.NET Core** properly installed ([instructions here](Linux.md)).
|
||||
|
||||
You can use Cron on macOS, but [this method](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/scheduling-MacOS.md) is preferred.
|
||||
|
||||
---
|
||||
## Creating the script
|
||||
|
||||
1. Open Terminal and create a new text file with `nano /path/to/DiscordChatExporter/cron.sh`
|
||||
|
||||
@@ -66,8 +64,8 @@ exit 0
|
||||
|
||||
3. Replace:
|
||||
|
||||
- `tokenhere` with your [Token](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md).
|
||||
- `channelhere` with a [Channel ID](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md).
|
||||
- `tokenhere` with your [Token](Token-and-IDs.md).
|
||||
- `channelhere` with a [Channel ID](Token-and-IDs.md).
|
||||
- `dceFOLDERpathhere` with DCE's **directory path** (e.g. `/path/to/folder`, NOT `/path/to/folder/DiscordChatExporter.dll`).
|
||||
- `filenamehere` with the exported channel's filename, without spaces.
|
||||
- `dirhere` with the export directory (e.g. /home/user/Documents/Discord\ Exports).
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Scheduling on macOS is a bit tricky, but it should work if you follow the instructions accordingly.
|
||||
|
||||
Make sure you already have **DiscordChatExporter.CLI** and **.NET Core** properly installed ([instructions here](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/macOS-usage-instructions.md)).
|
||||
Make sure you already have **DiscordChatExporter.CLI** and **.NET Core** properly installed ([instructions here](MacOS.md)).
|
||||
|
||||
## Creating the script
|
||||
|
||||
@@ -70,8 +70,8 @@ exit 0
|
||||
|
||||
4. Replace:
|
||||
|
||||
- `tokenhere` with your [Token](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md)
|
||||
- `channelhere` with a [Channel ID](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md)
|
||||
- `tokenhere` with your [Token](Token-and-IDs.md)
|
||||
- `channelhere` with a [Channel ID](Token-and-IDs.md)
|
||||
- `dceFOLDERpathhere` with DCE's **directory's path** (e.g. `/Users/user/Desktop/DiscordChatExporterFolder`, NOT `/Users/user/Desktop/DiscordChatExporterFolder/DiscordChatExporter.DLL`)
|
||||
- `filenamehere` with the exported channel's filename, without spaces
|
||||
- `dirhere` with the directory you want the files to be saved at (e.g. `/Users/user/Documents/Discord\ Exports`)
|
||||
@@ -168,7 +168,7 @@ Omitted keys are interpreted as wildcards, for example, if you delete the Minute
|
||||
|
||||
Be aware that if you set the day to '31', the script will only run on months that have the 31st day.
|
||||
|
||||
**Check the examples below ([or skip to step 3 (loading the file)](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/scheduling-MacOS.md#3-loading-the-plist-into-launchctl)):**
|
||||
**Check the examples below ([or skip to step 3 (loading the file)](#3-loading-the-plist-into-launchctl)):**
|
||||
|
||||
Export everyday at 5:15 PM:
|
||||
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
We'll be using [DiscordChatExporter CLI](https://github.com/Tyrrrz/DiscordChatExporter/releases/latest), PowerShell, and Task Scheduler.
|
||||
|
||||
## Creating the script
|
||||
|
||||
1. Open a text editor such as Notepad and paste:
|
||||
|
||||
```console
|
||||
# Info: https://github.com/Tyrrrz/DiscordChatExporter/wiki
|
||||
# Info: https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs
|
||||
|
||||
$TOKEN = "tokenhere"
|
||||
$CHANNEL = "channelhere"
|
||||
@@ -31,8 +33,8 @@ exit
|
||||
|
||||
2. Replace:
|
||||
|
||||
- `tokenhere` with your [Token](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md)
|
||||
- `channelhere` with a [Channel ID](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md)
|
||||
- `tokenhere` with your [Token](Token-and-IDs.md)
|
||||
- `channelhere` with a [Channel ID](Token-and-IDs.md)
|
||||
- `exefolderhere` with the .exe **directory's path** (e.g. C:\Users\User\Desktop\DiscordChatExporter)
|
||||
- `filenamehere` with a filename without spaces
|
||||
- `dirhere` with the export directory (e.g. C:\Users\User\Documents\Exports)
|
||||
|
||||
@@ -48,12 +48,12 @@ Prerequisite step: Navigate to [discord.com](https://discord.com) and login.
|
||||
<br clear="right" />
|
||||
<br />
|
||||
|
||||
4. <img width="500" align="right" src="https://i.imgur.com/rnZG8Id.png" />Click the text box labelled `Filter` and type `library`. The entries will filter down to a single entry named `library`.
|
||||
4. <img width="500" align="right" src="https://i.imgur.com/rnZG8Id.png" />Click the text box labelled `Filter` and type `messages`. The entries will filter down to a single request named `messages`. If the request doesn't appear, switch to any other Discord channel to trigger it.
|
||||
|
||||
<br clear="right" />
|
||||
<br />
|
||||
|
||||
5. <img width="500" align="right" src="https://i.imgur.com/29dE3fR.png" />Click the entry named `library`. A panel will open to the right and display details about the entry. Click the `Headers` tab if it isn't already active.
|
||||
5. <img width="500" align="right" src="https://i.imgur.com/29dE3fR.png" />Click the entry named `messages`. A panel will open to the right and display details about the entry. Click the `Headers` tab if it isn't already active.
|
||||
|
||||
<br clear="right" />
|
||||
<br />
|
||||
@@ -136,12 +136,12 @@ Prerequisite step: Navigate to [discord.com](https://discord.com) and login.
|
||||
<br clear="right" />
|
||||
<br />
|
||||
|
||||
3. <img width="500" align="right" src="https://i.imgur.com/efUCfBO.png" />Type `library` into the filter. The network request list will filter out any entries not containing the string `library`.
|
||||
3. <img width="500" align="right" src="https://i.imgur.com/efUCfBO.png" />Type `messages` into the filter. The network request list will filter out any entries not containing the string `messages`. If the request doesn't appear, switch to any other Discord channel to trigger it.
|
||||
|
||||
<br clear="right" />
|
||||
<br />
|
||||
|
||||
4. <img width="500" align="right" src="https://i.imgur.com/cdJZ7Q1.png" />Click `library`. The [network request details pane](https://firefox-source-docs.mozilla.org/devtools-user/network_monitor/request_details/index.html) will display. The [headers tab](https://firefox-source-docs.mozilla.org/devtools-user/network_monitor/request_details/index.html#network-monitor-request-details-headers-tab) should be active by default. If it isn’t, click it.
|
||||
4. <img width="500" align="right" src="https://i.imgur.com/cdJZ7Q1.png" />Click `messages`. The [network request details pane](https://firefox-source-docs.mozilla.org/devtools-user/network_monitor/request_details/index.html) will display. The [headers tab](https://firefox-source-docs.mozilla.org/devtools-user/network_monitor/request_details/index.html#network-monitor-request-details-headers-tab) should be active by default. If it isn’t, click it.
|
||||
|
||||
<br clear="right" />
|
||||
<br />
|
||||
@@ -232,7 +232,7 @@ Prerequisite step: Navigate to [discord.com](https://discord.com) and login.
|
||||
|
||||
4. Launch Discord.
|
||||
|
||||
5. To find your user token, continue [here](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md#in-chrome).
|
||||
5. To find your user token, continue [here](#in-chrome).
|
||||
|
||||
#### Via settings menu (BetterDiscord only)
|
||||
|
||||
@@ -252,7 +252,7 @@ Prerequisite step: Navigate to [discord.com](https://discord.com) and login.
|
||||
<br />
|
||||
|
||||
4. Press <kbd>Esc</kbd>. The settings page will close.
|
||||
5. To find your user token, continue [here](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md#in-chrome).
|
||||
5. To find your user token, continue [here](#in-chrome).
|
||||
|
||||
## How to get a Bot Token
|
||||
|
||||
|
||||
+16
-21
@@ -20,7 +20,7 @@ A token can be used to log into your account, so treat it like a password and ne
|
||||
|
||||
### How can I reset my token?
|
||||
|
||||
Follow the [instructions here](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md).
|
||||
Follow the [instructions here](Token-and-IDs.md).
|
||||
|
||||
### Will I get banned if I use this?
|
||||
|
||||
@@ -66,31 +66,26 @@ No.
|
||||
|
||||
### How can I find my token?
|
||||
|
||||
Check the following page: [Obtaining token](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md)
|
||||
Check the following page: [Obtaining token](Token-and-IDs.md)
|
||||
|
||||
### When I open DCE a black window pops up quickly or nothing shows up
|
||||
|
||||
If you have [.NET Core Runtime correctly installed](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Dotnet.md), you might have downloaded the CLi flavor, try [downloading the GUI](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#gui-or-cli) instead.
|
||||
|
||||
### I can't open DCE, it sends me to a Visual Studio webpage
|
||||
|
||||
Check the following page:
|
||||
[Installation and usage](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Readme.md#installation--usage)
|
||||
If you have [.NET Core Runtime correctly installed](Dotnet.md), you might have downloaded the CLi flavor, try [downloading the GUI](Getting-started.md#gui-or-cli) instead.
|
||||
|
||||
### How do I run DCE on macOS or Linux?
|
||||
|
||||
Check the following pages:
|
||||
|
||||
- [macOS usage instructions](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/MacOS.md)
|
||||
- [Linux usage instructions](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Linux.md)
|
||||
- [macOS usage instructions](MacOS.md)
|
||||
- [Linux usage instructions](Linux.md)
|
||||
|
||||
### How can I set DCE to export automatically at certain times?
|
||||
|
||||
Check the following pages to learn how to schedule **DiscordChatExporter.CLI** runs (advanced):
|
||||
|
||||
- [Windows scheduling](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/scheduling-windows.md)
|
||||
- [macOS scheduling](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/scheduling-MacOS.md)
|
||||
- [Linux scheduling](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/scheduling-Linux.md)
|
||||
- [Windows scheduling](Scheduling-Windows.md)
|
||||
- [macOS scheduling](Scheduling-MacOS.md)
|
||||
- [Linux scheduling](Scheduling-Linux.md)
|
||||
|
||||
### The exported file is too large, I can't open it
|
||||
|
||||
@@ -98,13 +93,13 @@ Try opening it with a different program, try partitioning or use a different fil
|
||||
|
||||
### DCE is crashing/failing
|
||||
|
||||
Check the following page: [Installing .NET Core Runtime](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Dotnet.md)
|
||||
Check the following page: [Installing .NET Core Runtime](Dotnet.md)
|
||||
|
||||
If you already have .NET Core installed, please check if your problem is a [known issue](https://github.com/Tyrrrz/DiscordChatExporter/issues?q=is%3Aissue) before [opening a bug report](https://github.com/Tyrrrz/DiscordChatExporter/issues/new).
|
||||
|
||||
### .NET Core Runtime is required
|
||||
|
||||
Check the following page: [Installing .NET Core Runtime](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Dotnet.md)
|
||||
Check the following page: [Installing .NET Core Runtime](Dotnet.md)
|
||||
|
||||
### I see messages in the export, but they have no content
|
||||
|
||||
@@ -116,25 +111,25 @@ Your bot is missing the 'Message Content Intent'. Go to the [Discord Developer P
|
||||
|
||||
Check the following page:
|
||||
|
||||
- [Using the CLI](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#using-the-cli)
|
||||
- [Using the CLI](Using-the-CLI.md)
|
||||
|
||||
If you're using **Docker**, please refer to the [Docker Usage Instructions](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Docker.md) instead.
|
||||
If you're using **Docker**, please refer to the [Docker Usage Instructions](Docker.md) instead.
|
||||
|
||||
### Where can I find the 'Channel IDs'?
|
||||
|
||||
Check the following page:
|
||||
|
||||
- [Obtaining Channel IDs](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md)
|
||||
- [Obtaining Channel IDs](Token-and-IDs.md)
|
||||
|
||||
### I can't find Docker exported chats
|
||||
|
||||
Check the following page:
|
||||
|
||||
- [Docker usage instructions](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/docker)
|
||||
- [Docker usage instructions](Docker.md)
|
||||
|
||||
### I can't export Direct Messages
|
||||
|
||||
Make sure you're [copying the DM Channel ID](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md#how-to-get-a-direct-message-channel-id), not the person's user ID.
|
||||
Make sure you're [copying the DM Channel ID](Token-and-IDs.md#how-to-get-a-direct-message-channel-id), not the person's user ID.
|
||||
|
||||
## Errors
|
||||
|
||||
@@ -149,7 +144,7 @@ DiscordChatExporter.Domain.Exceptions.DiscordChatExporterException: Authenticati
|
||||
DiscordChatExporter.Domain.Exceptions.DiscordChatExporterException: Requested resource does not exist.
|
||||
```
|
||||
|
||||
↳ Check your channel ID, it might be invalid. [Read this if you need help](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md).
|
||||
↳ Check your channel ID, it might be invalid. [Read this if you need help](Token-and-IDs.md).
|
||||
|
||||
```console
|
||||
DiscordChatExporter.Domain.Exceptions.DiscordChatExporterException: Access is forbidden.
|
||||
|
||||
+70
-166
@@ -3,8 +3,8 @@
|
||||
## Guide
|
||||
|
||||
> **Note**:
|
||||
> Make sure you have [.NET Core installed](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Dotnet.md) before attempting to run the commands below.
|
||||
> **Docker** users, please refer to the [Docker usage instructions](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Docker.md).
|
||||
> Make sure you have [.NET Core installed](Dotnet.md) before attempting to run the commands below.
|
||||
> **Docker** users, please refer to the [Docker usage instructions](Docker.md).
|
||||
|
||||
## Step 1
|
||||
|
||||
@@ -25,7 +25,8 @@ You can also drag and drop the folder on **every platform**.
|
||||
|
||||
## Step 3
|
||||
|
||||
Now we're ready to run the commands. The examples on this page follow the Windows file path format, change the file paths according to your system.
|
||||
Now we're ready to run the commands. The examples on this page follow the Windows file path format, change the file
|
||||
paths according to your system.
|
||||
|
||||
Type the following in Command Prompt (Terminal), then press ENTER to run it. This will list DCE's options.
|
||||
|
||||
@@ -33,52 +34,36 @@ Type the following in Command Prompt (Terminal), then press ENTER to run it. Thi
|
||||
dotnet DiscordChatExporter.Cli.dll
|
||||
```
|
||||
|
||||
> **Docker** users, please refer to the [Docker usage instructions](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Docker.md).
|
||||
> **Docker** users, please refer to the [Docker usage instructions](Docker.md).
|
||||
|
||||
## CLI commands
|
||||
|
||||
| Command | Description |
|
||||
| ------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
|
||||
| [export](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#export) | Exports a channel |
|
||||
| [exportdm](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#exportdm) | Exports all direct message channels |
|
||||
| [exportguild](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#exportguild) | Exports all channels within the specified server |
|
||||
| [exportall](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#exportall) | Exports all accessible channels |
|
||||
| [channels](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#channels) | Outputs the list of channels in the given server |
|
||||
| [dm](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#dm) | Outputs the list of direct message channels |
|
||||
| [guilds](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#guilds) | Outputs the list of accessible servers |
|
||||
| [guide](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#guide) | Explains how to obtain token, guild, and channel ID |
|
||||
| Command | Description |
|
||||
|-------------------------|-----------------------------------------------------|
|
||||
| export | Exports a channel |
|
||||
| exportdm | Exports all direct message channels |
|
||||
| exportguild | Exports all channels within the specified server |
|
||||
| exportall | Exports all accessible channels |
|
||||
| channels | Outputs the list of channels in the given server |
|
||||
| dm | Outputs the list of direct message channels |
|
||||
| guilds | Outputs the list of accessible servers |
|
||||
| guide | Explains how to obtain token, guild, and channel ID |
|
||||
|
||||
To use the commands, you'll need a token. For the instructions on how to get a token, please refer to [this page](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md), or run `dotnet DiscordChatExporter.Cli.dll guide`.
|
||||
To get help with a specific command, please run:
|
||||
To use the commands, you'll need a token. For the instructions on how to get a token, please refer to [this page](Token-and-IDs.md), or run `dotnet DiscordChatExporter.Cli.dll guide`.
|
||||
|
||||
To get help with a specific command, run:
|
||||
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll command -h
|
||||
dotnet DiscordChatExporter.Cli.dll command --help
|
||||
```
|
||||
|
||||
### `export`
|
||||
For example, to figure out how to use the `export` command, run:
|
||||
|
||||
With this command, you can export **server channels** and **direct messages**.
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll export --help
|
||||
```
|
||||
|
||||
| | Option | Description |
|
||||
| ------ | --------------------------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| **\*** | [-c](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#basic-usage) | [Channel ID(s)](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md#how-to-get-guild-id-or-guild-channel-id) |
|
||||
| **\*** | [-t](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#basic-usage) | [Authorization token](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md#how-to-get-user-token). Environment variable: `DISCORD_TOKEN` |
|
||||
| | [-o](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#changing-the-output-filename) | Output file or directory path |
|
||||
| | [-f](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#changing-the-format) | [Output file format](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#file-formats). Default: HtmlDark |
|
||||
| | [--after](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#date-ranges) | Only include messages sent after this date |
|
||||
| | [--before](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#date-ranges) | Only include messages sent before this date |
|
||||
| | [-p](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#partitioning) | Split output into partitions, each limited to this number of messages (e.g. 100) or file size (e.g. 10mb) |
|
||||
| | [--filter](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Message-filters.md) | Special notation for filtering the messages that get included in the export |
|
||||
| | [--media](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#downloading-assets) | Download assets referenced by the export (user avatars, attached files, embedded images, etc.). Default: false |
|
||||
| | [--reuse-media](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#reuse-assets) | Reuse previously downloaded assets to avoid redundant requests. Default: false |
|
||||
| | [--media-dir](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#downloading-assets) | Directory to store assets from all exported channels in the same place |
|
||||
| | [--locale](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#changing-the-date-format) | Format used when writing dates. Default: en-US |
|
||||
| | -h | Shows help text |
|
||||
|
||||
> **Note**:
|
||||
> Options with an asterisk (**\***) are required. The order of the options doesn't matter.
|
||||
|
||||
#### Basic usage
|
||||
## Export a specific channel
|
||||
|
||||
You can quickly export with DCE's default settings by using just `-t token` and `-c channelid`.
|
||||
|
||||
@@ -88,7 +73,8 @@ dotnet DiscordChatExporter.Cli.dll export -t "mfa.Ifrn" -c 53555
|
||||
|
||||
#### Changing the format
|
||||
|
||||
You can change the export format to `HtmlDark`, `HtmlLight`, `PlainText` `Json` or `Csv` with `-f format`. The default format is `HtmlDark`.
|
||||
You can change the export format to `HtmlDark`, `HtmlLight`, `PlainText` `Json` or `Csv` with `-f format`. The default
|
||||
format is `HtmlDark`.
|
||||
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll export -t "mfa.Ifrn" -c 53555 -f Json
|
||||
@@ -104,7 +90,8 @@ dotnet DiscordChatExporter.Cli.dll export -t "mfa.Ifrn" -c 53555 -o myserver.htm
|
||||
|
||||
#### Changing the output directory
|
||||
|
||||
You can change the export directory by using `-o` and providing a path that ends with a slash or does not have a file extension.
|
||||
You can change the export directory by using `-o` and providing a path that ends with a slash or does not have a file
|
||||
extension.
|
||||
If any of the folders in the path have a space in its name, escape them with quotes (").
|
||||
|
||||
```console
|
||||
@@ -129,7 +116,9 @@ You can use template tokens to generate the output file path based on the guild
|
||||
dotnet DiscordChatExporter.Cli.dll export -t "mfa.Ifrn" -c 53555 -o "C:\Discord Exports\%G\%T\%C.html"
|
||||
```
|
||||
|
||||
Assuming you are exporting a channel named `"my-channel"` in the `"Text channels"` category from a server called `"My server"`, you will get the following output file path: `C:\Discord Exports\My server\Text channels\my-channel.html`
|
||||
Assuming you are exporting a channel named `"my-channel"` in the `"Text channels"` category from a server
|
||||
called `"My server"`, you will get the following output file
|
||||
path: `C:\Discord Exports\My server\Text channels\my-channel.html`
|
||||
|
||||
Here is the full list of supported template tokens:
|
||||
|
||||
@@ -163,7 +152,8 @@ dotnet DiscordChatExporter.Cli.dll export -t "mfa.Ifrn" -c 53555 -p 20mb
|
||||
#### Downloading assets
|
||||
|
||||
If this option is set, the export will include additional files such as user avatars, attached files, images, etc.
|
||||
Only files that are referenced by the export are downloaded, which means that, for example, user avatars will not be downloaded when using the plain text (TXT) export format.
|
||||
Only files that are referenced by the export are downloaded, which means that, for example, user avatars will not be
|
||||
downloaded when using the plain text (TXT) export format.
|
||||
A folder containing the assets will be created along with the exported chat. They must be kept together.
|
||||
|
||||
```console
|
||||
@@ -172,7 +162,8 @@ dotnet DiscordChatExporter.Cli.dll export -t "mfa.Ifrn" -c 53555 --media
|
||||
|
||||
#### Reusing assets
|
||||
|
||||
Previously downloaded assets can be reused to skip redundant downloads as long as the chat is always exported to the same folder. Using this option can speed up future exports. This option requires the `--media` option.
|
||||
Previously downloaded assets can be reused to skip redundant downloads as long as the chat is always exported to the
|
||||
same folder. Using this option can speed up future exports. This option requires the `--media` option.
|
||||
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll export -t "mfa.Ifrn" -c 53555 --media --reuse-media
|
||||
@@ -180,7 +171,8 @@ dotnet DiscordChatExporter.Cli.dll export -t "mfa.Ifrn" -c 53555 --media --reuse
|
||||
|
||||
#### Changing the media directory
|
||||
|
||||
By default, the media directory is created alongside the exported chat. You can change this by using `--media-dir` and providing a path that ends with a slash. All of the exported media will be stored in this directory.
|
||||
By default, the media directory is created alongside the exported chat. You can change this by using `--media-dir` and
|
||||
providing a path that ends with a slash. All of the exported media will be stored in this directory.
|
||||
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll export -t "mfa.Ifrn" -c 53555 --media --media-dir "C:\Discord Media"
|
||||
@@ -188,7 +180,8 @@ dotnet DiscordChatExporter.Cli.dll export -t "mfa.Ifrn" -c 53555 --media --media
|
||||
|
||||
#### Changing the date format
|
||||
|
||||
You can customize how dates are formatted in the exported files by using `--locale` and inserting one of Discord's locales. The default locale is `en-US`.
|
||||
You can customize how dates are formatted in the exported files by using `--locale` and inserting one of Discord's
|
||||
locales. The default locale is `en-US`.
|
||||
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll export -t "mfa.Ifrn" -c 53555 --locale "de-DE"
|
||||
@@ -211,67 +204,32 @@ dotnet DiscordChatExporter.Cli.dll export -t "mfa.Ifrn" -c 53555 --after "2019-0
|
||||
```
|
||||
|
||||
**Messages sent in a date range**
|
||||
Use `--before` and `--after` to export messages sent during the provided date range. E.g. messages sent between September 17th, 2019 11:34 PM and September 18th:
|
||||
Use `--before` and `--after` to export messages sent during the provided date range. E.g. messages sent between
|
||||
September 17th, 2019 11:34 PM and September 18th:
|
||||
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll export -t "mfa.Ifrn" -c 53555 --after "2019-09-17 23:34" --before "2019-09-18"
|
||||
```
|
||||
|
||||
You can try different formats like `17-SEP-2019 11:34 PM` or even refine your ranges down to milliseconds `17-SEP-2019 23:45:30.6170`!
|
||||
You can try different formats like `17-SEP-2019 11:34 PM` or even refine your ranges down to
|
||||
milliseconds `17-SEP-2019 23:45:30.6170`!
|
||||
Don't forget to quote (") the date if it has spaces!
|
||||
More info about .NET date formats [here](https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings).
|
||||
More info about .NET date
|
||||
formats [here](https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings).
|
||||
|
||||
### `exportdm`
|
||||
### Export channels from a specific guild (server)
|
||||
|
||||
This command exports all your **direct messages**.
|
||||
To export all channels in a specific guild, use the `exportguild` command and provide the guild ID through the `-g|--guild` option:
|
||||
|
||||
| | Option | Description |
|
||||
| ------ | --------------------------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| **\*** | [-c](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#basic-usage) | [Channel ID(s)](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md#how-to-get-guild-id-or-guild-channel-id) |
|
||||
| **\*** | [-t](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#basic-usage) | [Authorization token](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md#how-to-get-user-token). Environment variable: `DISCORD_TOKEN` |
|
||||
| | [-o](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#changing-the-output-filename) | Output file or directory path |
|
||||
| | [-f](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#changing-the-format) | [Output file format](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#file-formats). Default: HtmlDark |
|
||||
| | [--after](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#date-ranges) | Only include messages sent after this date |
|
||||
| | [--before](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#date-ranges) | Only include messages sent before this date |
|
||||
| | [-p](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#partitioning) | Split output into partitions, each limited to this number of messages (e.g. 100) or file size (e.g. 10mb) |
|
||||
| | [--filter](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Message-filters.md) | Special notation for filtering the messages that get included in the export |
|
||||
| | [--media](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#downloading-assets) | Download assets referenced by the export (user avatars, attached files, embedded images, etc.). Default: false |
|
||||
| | [--reuse-media](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#reuse-assets) | Reuse previously downloaded assets to avoid redundant requests. Default: false |
|
||||
| | [--media-dir](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#downloading-assets) | Directory to store assets from all exported channels in the same place |
|
||||
| | [--locale](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#changing-the-date-format) | Format used when writing dates. Default: en-US |
|
||||
| | -h | Shows help text |
|
||||
|
||||
> **Note**:
|
||||
> Options with an asterisk (**\***) are required. The order of the options doesn't matter.
|
||||
|
||||
### `exportguild`
|
||||
|
||||
This command exports all channels of a **server**.
|
||||
|
||||
| | Option | Description |
|
||||
| ------ | ------------------------------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| **\*** | -g | [Server ID](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md#how-to-get-guild-id-or-guild-channel-id) |
|
||||
| **\*** | [-t](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#basic-usage) | [Authorization token](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md#how-to-get-user-token). Environment variable: `DISCORD_TOKEN` |
|
||||
| | [-o](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#changing-the-output-filename) | Output file or directory path |
|
||||
| | [-f](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#changing-the-format) | [Output file format](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#file-formats). Default: HtmlDark |
|
||||
| | [--after](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#date-ranges) | Only include messages sent after this date |
|
||||
| | [--before](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#date-ranges) | Only include messages sent before this date |
|
||||
| | [-p](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#partitioning) | Split output into partitions, each limited to this number of messages (e.g. 100) or file size (e.g. 10mb) |
|
||||
| | [--filter](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Message-filters.md) | Special notation for filtering the messages that get included in the export |
|
||||
| | [--media](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#downloading-assets) | Download assets referenced by the export (user avatars, attached files, embedded images, etc.). Default: false |
|
||||
| | [--reuse-media](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#reuse-assets) | Reuse previously downloaded assets to avoid redundant requests. Default: false |
|
||||
| | [--media-dir](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#downloading-assets) | Directory to store assets from all exported channels in the same place |
|
||||
| | [--locale](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#changing-the-date-format) | Format used when writing dates. Default: en-US |
|
||||
| | [--include-threads](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#including-threads) | Specify whether to include threads (and which type) in the export. By default, threads are not included. It has possible values of `none`, `active`, or `all`, indicating which threads should be included. To include both active and archived threads, use `--include-threads all`. |
|
||||
| | [--include-vc](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#including-voice-channels) | Include voice channels in the export. Default: true |
|
||||
| | -h | Shows help text |
|
||||
|
||||
> **Note**:
|
||||
> Options with an asterisk (**\***) are required. The order of the options doesn't matter.
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll exportguild -t "mfa.Ifrn" -g 21814
|
||||
```
|
||||
|
||||
#### Including threads
|
||||
|
||||
By default, threads are not included in the export. You can change this behavior by using `--include-threads` and specifying which threads should be included. It has possible values of `none`, `active`, or `all`, indicating which threads should be included. To include both active and archived threads, use `--include-threads all`.
|
||||
By default, threads are not included in the export. You can change this behavior by using `--include-threads` and
|
||||
specifying which threads should be included. It has possible values of `none`, `active`, or `all`, indicating which
|
||||
threads should be included. To include both active and archived threads, use `--include-threads all`.
|
||||
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll exportguild -t "mfa.Ifrn" -g 21814 --include-threads all
|
||||
@@ -279,36 +237,21 @@ dotnet DiscordChatExporter.Cli.dll exportguild -t "mfa.Ifrn" -g 21814 --include-
|
||||
|
||||
#### Including voice channels
|
||||
|
||||
By default, voice channels are included in the export. You can change this behavior by using `--include-vc` and specifying whether to include voice channels in the export. It has possible values of `true` or `false`, to exclude voice channels, use `--include-vc false`.
|
||||
By default, voice channels are included in the export. You can change this behavior by using `--include-vc` and
|
||||
specifying whether to include voice channels in the export. It has possible values of `true` or `false`, to exclude
|
||||
voice channels, use `--include-vc false`.
|
||||
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll exportguild -t "mfa.Ifrn" -g 21814 --include-vc false
|
||||
```
|
||||
|
||||
### `exportall`
|
||||
### Export all channels
|
||||
|
||||
This command exports **all accessible channels**, including server channels and DMs.
|
||||
To export all accessible channels, use the `exportall` command:
|
||||
|
||||
| | Option | Description |
|
||||
| ------ | ------------------------------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| **\*** | [-t](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#basic-usage) | [Authorization token](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md#how-to-get-user-token). Environment variable: `DISCORD_TOKEN` |
|
||||
| | [-o](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#changing-the-output-filename) | Output file or directory path |
|
||||
| | [-f](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#changing-the-format) | [Output file format](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#file-formats). Default: HtmlDark |
|
||||
| | [--after](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#date-ranges) | Only include messages sent after this date |
|
||||
| | [--before](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#date-ranges) | Only include messages sent before this date |
|
||||
| | [-p](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#partitioning) | Split output into partitions, each limited to this number of messages (e.g. 100) or file size (e.g. 10mb) |
|
||||
| | [--filter](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Message-filters.md) | Special notation for filtering the messages that get included in the export |
|
||||
| | [--media](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#downloading-assets) | Download assets referenced by the export (user avatars, attached files, embedded images, etc.). Default: false |
|
||||
| | [--reuse-media](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#reuse-assets) | Reuse previously downloaded assets to avoid redundant requests. Default: false |
|
||||
| | [--media-dir](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#downloading-assets) | Directory to store assets from all exported channels in the same place |
|
||||
| | [--locale](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#changing-the-date-format) | Format used when writing dates. Default: en-US |
|
||||
| | [--include-threads](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#including-threads) | Specify whether to include threads (and which type) in the export. By default, threads are not included. It has possible values of `none`, `active`, or `all`, indicating which threads should be included. To include both active and archived threads, use `--include-threads all`. |
|
||||
| | [--include-vc](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#including-voice-channels) | Include voice channels in the export. Default: true |
|
||||
| | [--include-dm](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#excluding-dms) | Include direct messages in the export. Default: true |
|
||||
| | -h | Shows help text |
|
||||
|
||||
> **Note**:
|
||||
> Options with an asterisk (**\***) are required. The order of the options doesn't matter.
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll exportall -t "mfa.Ifrn"
|
||||
```
|
||||
|
||||
#### Excluding DMs
|
||||
|
||||
@@ -318,65 +261,26 @@ To exclude DMs, add the `--include-dm false` option.
|
||||
dotnet DiscordChatExporter.Cli.dll exportall -t "mfa.Ifrn" --include-dm false
|
||||
```
|
||||
|
||||
### `channels`
|
||||
### List channels in a guild (server)
|
||||
|
||||
This command outputs a **server's channels** in the following format:
|
||||
`Channel ID | Channel Name`
|
||||
To save the output to a file, run the command below. If the file already exists, it will be overwritten.
|
||||
|
||||
| | Option | Description |
|
||||
| ------ | ---------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| **\*** | -g | [Server ID](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md#how-to-get-guild-id-or-guild-channel-id) |
|
||||
| **\*** | [-t](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#basic-usage) | [Authorization token](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md#how-to-get-user-token). Environment variable: `DISCORD_TOKEN` |
|
||||
| | [--include-threads](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#including-threads) | Specify whether to include threads (and which type) in the output. By default, threads are not included. It has possible values of `none`, `active`, or `all`, indicating which threads should be included. To include both active and archived threads, use `--include-threads all`. |
|
||||
| | [--include-vc](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Using-the-CLI.md#including-voice-channels) | Include voice channels in the output. Default: true |
|
||||
| | -h | Shows help text |
|
||||
|
||||
> **Note**:
|
||||
> Options with an asterisk (**\***) are required. The order of the options doesn't matter.
|
||||
|
||||
To save the output to a file, run the command with `> C:\path\…` like the example below. If the file already exists, it will be overwritten.
|
||||
To list the channels available in a specific guild, use the `channels` command and provide the guild ID through the `-g|--guild` option:
|
||||
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll channels -t "mfa.Ifrn" -g 21814 > C:\path\to\output.txt
|
||||
dotnet DiscordChatExporter.Cli.dll channels -t "mfa.Ifrn" -g 21814
|
||||
```
|
||||
|
||||
### `dm`
|
||||
### List direct message channels
|
||||
|
||||
This command outputs a list of your **direct messages**.
|
||||
|
||||
| | Option | Description |
|
||||
| ------ | ---------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| **\*** | [-t](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#basic-usage) | [Authorization token](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md#how-to-get-user-token). Environment variable: `DISCORD_TOKEN` |
|
||||
| | -h | Shows help text |
|
||||
|
||||
> **Note**:
|
||||
> Options with an asterisk (**\***) are required. The order of the options doesn't matter.
|
||||
|
||||
To save the output to a file, run the command with `> C:\path\…` like the example below. If the file already exists, it will be overwritten.
|
||||
To list all DM channels accessible to the current account, use the `dm` command:
|
||||
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll dm -t "mfa.Ifrn" > C:\path\to\output.txt
|
||||
dotnet DiscordChatExporter.Cli.dll dm -t "mfa.Ifrn"
|
||||
```
|
||||
|
||||
### `guilds`
|
||||
### List guilds (servers)
|
||||
|
||||
This command outputs a list of your **servers**.
|
||||
|
||||
| | Option | Description |
|
||||
| ------ | ---------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| **\*** | [-t](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Getting-started.md#basic-usage) | [Authorization token](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md#how-to-get-user-token). Environment variable: `DISCORD_TOKEN` |
|
||||
| | -h | Shows help text |
|
||||
|
||||
> **Note**:
|
||||
> Options with an asterisk (**\***) are required. The order of the options doesn't matter.
|
||||
|
||||
To save the output to a file, run the command with `> C:\path\…` like the example below. If the file already exists, it will be overwritten.
|
||||
To list all guilds accessible by the current account, use the `guilds` command:
|
||||
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll guilds -t "mfa.Ifrn" > C:\path\to\output.txt
|
||||
```
|
||||
|
||||
### `guide`
|
||||
|
||||
This command explains [how to get your token, guild, and channel IDs](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Token-and-IDs.md).
|
||||
```
|
||||
@@ -46,7 +46,7 @@ In this screen you can customize the following:
|
||||
|
||||
- **Partition limit** (Optional) - Split output into partitions, each limited to this number of messages (e.g. 100) or file size (e.g. 10mb). For example, a channel with 36 messages set to be partitioned every 10 messages will output 4 files.
|
||||
|
||||
- **Message Filter** (Optional) - Special notation for filtering the messages that get included in the export. See [Message filters](https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs/Message-filters.md) for more info.
|
||||
- **Message Filter** (Optional) - Special notation for filtering the messages that get included in the export. See [Message filters](Message-filters.md) for more info.
|
||||
|
||||
- **Format markdown** (Optional) - Disable markdown processing when exporting. You can use this to produce JSON or plain text exports without unwrapping mentions, custom emoji, and certain other special tokens.
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
name: docker
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
# Outputs from this job aren't really used, but it's here to verify that
|
||||
# the Dockerfile builds correctly on pull requests.
|
||||
build:
|
||||
pack:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: write
|
||||
@@ -22,11 +23,10 @@ jobs:
|
||||
|
||||
- name: Build image
|
||||
run: >
|
||||
docker buildx build
|
||||
docker buildx build .
|
||||
--file DiscordChatExporter.Cli.dockerfile
|
||||
--platform linux/amd64,linux/arm64
|
||||
--output type=tar,dest=DiscordChatExporter.Cli.Docker.tar
|
||||
.
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # 3.1.3
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
|
||||
deploy:
|
||||
# Deploy to DockerHub only on tag push or master branch push
|
||||
if: ${{ github.event_name == 'push' && (github.ref_type == 'tag' || github.ref_type == 'branch' && github.ref_name == 'master') }}
|
||||
if: ${{ github.ref_type == 'tag' || github.ref_type == 'branch' && github.ref_name == 'master' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -56,11 +56,10 @@ jobs:
|
||||
|
||||
- name: Build & push image
|
||||
run: >
|
||||
docker buildx build
|
||||
docker buildx build .
|
||||
--file DiscordChatExporter.Cli.dockerfile
|
||||
--platform linux/amd64,linux/arm64
|
||||
--push
|
||||
--tag tyrrrz/discordchatexporter:latest
|
||||
${{ github.ref_type == 'tag' && '--tag tyrrrz/discordchatexporter:$GITHUB_REF_NAME' || '' }}
|
||||
${{ github.ref_type == 'tag' && '--tag tyrrrz/discordchatexporter:stable' || '' }}
|
||||
.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
name: main
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
@@ -10,7 +11,7 @@ env:
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
format:
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -22,15 +23,36 @@ jobs:
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # 3.2.0
|
||||
with:
|
||||
dotnet-version: 7.0.x
|
||||
dotnet-version: 8.0.x
|
||||
|
||||
- name: Verify formatting
|
||||
run: >
|
||||
dotnet build
|
||||
-t:CSharpierFormat
|
||||
--configuration Release
|
||||
|
||||
test:
|
||||
# Tests need access to secrets, so we can't run them against PRs because of limited trust
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # 4.1.0
|
||||
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # 3.2.0
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
|
||||
- name: Run tests
|
||||
# Tests need access to secrets, so we can't run them against PRs because of limited trust
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
env:
|
||||
DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }}
|
||||
run: >
|
||||
dotnet test
|
||||
-p:CSharpier_Bypass=true
|
||||
--configuration Release
|
||||
--logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true"
|
||||
--collect:"XPlat Code Coverage"
|
||||
@@ -62,11 +84,12 @@ jobs:
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # 3.2.0
|
||||
with:
|
||||
dotnet-version: 7.0.x
|
||||
dotnet-version: 8.0.x
|
||||
|
||||
- name: Publish app
|
||||
run: >
|
||||
dotnet publish ${{ matrix.app }}
|
||||
-p:CSharpier_Bypass=true
|
||||
--output ${{ matrix.app }}/bin/publish/
|
||||
--configuration Release
|
||||
|
||||
@@ -78,9 +101,10 @@ jobs:
|
||||
if-no-files-found: error
|
||||
|
||||
release:
|
||||
if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }}
|
||||
if: ${{ github.ref_type == 'tag' }}
|
||||
|
||||
needs:
|
||||
- format
|
||||
- test
|
||||
- pack
|
||||
|
||||
|
||||
+6
-17
@@ -1,23 +1,12 @@
|
||||
# User-specific files
|
||||
.vs/
|
||||
.idea/
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
.idea/
|
||||
.vs/
|
||||
.vscode/
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
[Xx]64/
|
||||
[Xx]86/
|
||||
[Bb]uild/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
bin/
|
||||
obj/
|
||||
|
||||
# Coverage
|
||||
*.opencover.xml
|
||||
# Test results
|
||||
TestResults/
|
||||
@@ -1,5 +1,21 @@
|
||||
# Changelog
|
||||
|
||||
## v2.42.5 (23-Nov-2023)
|
||||
|
||||
- General changes:
|
||||
- Fixed an issue where the application crashed when trying to export a channel that contained a message with an invalid timestamp (e.g. `<t:0:x>`).
|
||||
|
||||
## v2.42.4 (16-Nov-2023)
|
||||
|
||||
- General changes:
|
||||
- Switched from .NET 7.0 to .NET 8.0. If running on Windows, the application should update all required prerequisites automatically. Alternatively, you can download the latest version of the runtime for your system [here](https://dotnet.microsoft.com/download/dotnet/8.0).
|
||||
- CLI changes:
|
||||
- Added a message that is displayed when the application is running with the output stream redirected, informing the user that they will not get rich progress reporting in this mode.
|
||||
- GUI changes:
|
||||
- Changed the presentation of the "Reuse assets" and "Assets path" options, such that the corresponding controls are now disabled if the "Download assets" option is not enabled.
|
||||
- HTML changes:
|
||||
- Fixed an issue where exporting a channel with a custom assets path could result in an HTML output that did not render properly in Firefox.
|
||||
|
||||
## v2.42.3 (09-Nov-2023)
|
||||
|
||||
- JSON changes:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Version>2.42.3</Version>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Version>2.42.5</Version>
|
||||
<Company>Tyrrrz</Company>
|
||||
<Copyright>Copyright (c) Oleksii Holub</Copyright>
|
||||
<LangVersion>preview</LangVersion>
|
||||
|
||||
@@ -11,15 +11,15 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AngleSharp" Version="1.0.5" />
|
||||
<PackageReference Include="AngleSharp" Version="1.0.7" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" PrivateAssets="all" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" PrivateAssets="all" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.2" PrivateAssets="all" />
|
||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||
<PackageReference Include="GitHubActionsTestLogger" Version="2.3.3" PrivateAssets="all" />
|
||||
<PackageReference Include="JsonExtensions" Version="1.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="ReflectionMagic" Version="5.0.0" />
|
||||
<PackageReference Include="xunit" Version="2.6.1" />
|
||||
|
||||
@@ -105,7 +105,7 @@ public static class ExportWrapper
|
||||
if (message is null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Message '{messageId}' does not exist in the export of channel '{channelId}'."
|
||||
$"Message #{messageId} not found in the export of channel #{channelId}."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ public static class ExportWrapper
|
||||
if (message.ValueKind == JsonValueKind.Undefined)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Message '{messageId}' does not exist in the export of channel '{channelId}'."
|
||||
$"Message #{messageId} not found in the export of channel #{channelId}."
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
# -- Build
|
||||
# Specify the platform here so that we pull the SDK image matching the host platform,
|
||||
# instead of the target platform specified during build by the `--platform` option.
|
||||
# Use the .NET 8.0 preview because the `--arch` option is only available in that version.
|
||||
# https://github.com/dotnet/dotnet-docker/issues/4388#issuecomment-1459038566
|
||||
# TODO: switch images to Alpine once .NET 8.0 is released.
|
||||
# Currently, the correct preview version is only available on Debian.
|
||||
# https://github.com/dotnet/dotnet-docker/blob/main/samples/selecting-tags.md
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0-preview AS build
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
|
||||
|
||||
# Expose the target architecture set by the `docker build --platform` option, so that
|
||||
# we can build the assembly for the correct platform.
|
||||
ARG TARGETARCH
|
||||
|
||||
WORKDIR /tmp/dce
|
||||
WORKDIR /tmp/app
|
||||
|
||||
COPY favicon.ico .
|
||||
COPY NuGet.config .
|
||||
@@ -31,7 +26,7 @@ RUN dotnet publish DiscordChatExporter.Cli \
|
||||
|
||||
# -- Run
|
||||
# Use `runtime-deps` instead of `runtime` because we have a self-contained assembly
|
||||
FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/runtime-deps:7.0 AS run
|
||||
FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/runtime-deps:8.0-alpine AS run
|
||||
|
||||
LABEL org.opencontainers.image.title="DiscordChatExporter.Cli"
|
||||
LABEL org.opencontainers.image.description="DiscordChatExporter is an application that can be used to export message history from any Discord channel to a file."
|
||||
@@ -40,14 +35,22 @@ LABEL org.opencontainers.image.url="https://github.com/Tyrrrz/DiscordChatExporte
|
||||
LABEL org.opencontainers.image.source="https://github.com/Tyrrrz/DiscordChatExporter/blob/master/DiscordChatExporter.Cli.dockerfile"
|
||||
LABEL org.opencontainers.image.licenses="MIT"
|
||||
|
||||
# Create a non-root user to run the app, so that the output files can be accessed by the host
|
||||
# Alpine image doesn't come with the ICU libraries pre-installed, so we need to install them manually.
|
||||
# We need the full ICU data because we allow the user to specify any locale for formatting purposes.
|
||||
RUN apk add --no-cache icu-libs
|
||||
RUN apk add --no-cache icu-data-full
|
||||
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
|
||||
ENV LC_ALL=en_US.UTF-8
|
||||
ENV LANG=en_US.UTF-8
|
||||
|
||||
# Use a non-root user to ensure that the files shared with the host are accessible by the host user.
|
||||
# We can use the default user provided by the base image for this purpose.
|
||||
# https://github.com/Tyrrrz/DiscordChatExporter/issues/851
|
||||
RUN adduser --disabled-password --no-create-home dce
|
||||
USER dce
|
||||
USER $APP_UID
|
||||
|
||||
# This directory is exposed to the user for mounting purposes, so it's important that it always
|
||||
# stays the same for backwards compatibility.
|
||||
WORKDIR /out
|
||||
|
||||
COPY --from=build /tmp/dce/DiscordChatExporter.Cli/bin/publish /opt/dce
|
||||
ENTRYPOINT ["/opt/dce/DiscordChatExporter.Cli"]
|
||||
COPY --from=build /tmp/app/DiscordChatExporter.Cli/bin/publish /opt/app
|
||||
ENTRYPOINT ["/opt/app/DiscordChatExporter.Cli"]
|
||||
@@ -48,6 +48,17 @@ public abstract class DiscordCommandBase : ICommand
|
||||
}
|
||||
#pragma warning restore CS0618
|
||||
|
||||
// Note about interactivity
|
||||
if (console.IsOutputRedirected)
|
||||
{
|
||||
console
|
||||
.Output
|
||||
.WriteLine(
|
||||
"Note: Output streams are redirected, rich console interactions are disabled. "
|
||||
+ "If you are running this command in Docker, consider allocating a pseudo-terminal for better user experience (docker run -it ...)."
|
||||
);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ using DiscordChatExporter.Core.Exceptions;
|
||||
using DiscordChatExporter.Core.Exporting;
|
||||
using DiscordChatExporter.Core.Exporting.Filtering;
|
||||
using DiscordChatExporter.Core.Exporting.Partitioning;
|
||||
using DiscordChatExporter.Core.Utils;
|
||||
using DiscordChatExporter.Core.Utils.Extensions;
|
||||
using Gress;
|
||||
using Spectre.Console;
|
||||
@@ -163,13 +162,14 @@ public abstract class ExportCommandBase : DiscordCommandBase
|
||||
|| OutputPath.Contains('%')
|
||||
// Otherwise, require an existing directory or an unambiguous directory path
|
||||
|| Directory.Exists(OutputPath)
|
||||
|| PathEx.IsDirectoryPath(OutputPath);
|
||||
|| Path.EndsInDirectorySeparator(OutputPath);
|
||||
|
||||
if (!isValidOutputPath)
|
||||
{
|
||||
throw new CommandException(
|
||||
"Attempted to export multiple channels, but the output path is neither a directory nor a template. "
|
||||
+ "If the provided output path is meant to be treated as a directory, make sure it ends with a slash."
|
||||
+ "If the provided output path is meant to be treated as a directory, make sure it ends with a slash. "
|
||||
+ $"Provided output path: '{OutputPath}'."
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,7 @@ public class GuideCommand : ICommand
|
||||
console.Output.WriteLine(" 4. Navigate to the Network tab");
|
||||
console.Output.WriteLine(" 5. Press Ctrl+R to reload");
|
||||
console.Output.WriteLine(" 6. Switch between random channels to trigger network requests");
|
||||
console
|
||||
.Output
|
||||
.WriteLine(" 7. Search for a request containing \"messages?limit=50\" or similar");
|
||||
console.Output.WriteLine(" 7. Search for a request that starts with \"messages\"");
|
||||
console.Output.WriteLine(" 8. Select the Headers tab on the right");
|
||||
console.Output.WriteLine(" 9. Scroll down to the Request Headers section");
|
||||
console.Output.WriteLine(" 10. Copy the value of the \"authorization\" header");
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CliFx" Version="2.3.4" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" PrivateAssets="all" />
|
||||
<PackageReference Include="CliFx" Version="2.3.5" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.2" PrivateAssets="all" />
|
||||
<PackageReference Include="Deorcify" Version="1.0.2" PrivateAssets="all" />
|
||||
<PackageReference Include="DotnetRuntimeBootstrapper" Version="2.5.1" PrivateAssets="all" />
|
||||
<PackageReference Include="Gress" Version="2.1.1" />
|
||||
|
||||
@@ -618,7 +618,7 @@ public class DiscordClient
|
||||
if (!application.IsMessageContentIntentEnabled)
|
||||
{
|
||||
throw new DiscordChatExporterException(
|
||||
"Bot account does not have the Message Content Intent enabled.",
|
||||
"Provided bot account does not have the Message Content Intent enabled.",
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,26 +22,27 @@ public partial record struct Snowflake
|
||||
public static Snowflake FromDate(DateTimeOffset instant) =>
|
||||
new(((ulong)instant.ToUnixTimeMilliseconds() - 1420070400000UL) << 22);
|
||||
|
||||
public static Snowflake? TryParse(string? str, IFormatProvider? formatProvider = null)
|
||||
public static Snowflake? TryParse(string? value, IFormatProvider? formatProvider = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(str))
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return null;
|
||||
|
||||
// As number
|
||||
if (ulong.TryParse(str, NumberStyles.None, formatProvider, out var value))
|
||||
return new Snowflake(value);
|
||||
if (ulong.TryParse(value, NumberStyles.None, formatProvider, out var number))
|
||||
return new Snowflake(number);
|
||||
|
||||
// As date
|
||||
if (DateTimeOffset.TryParse(str, formatProvider, DateTimeStyles.None, out var instant))
|
||||
if (DateTimeOffset.TryParse(value, formatProvider, DateTimeStyles.None, out var instant))
|
||||
return FromDate(instant);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Snowflake Parse(string str, IFormatProvider? formatProvider) =>
|
||||
TryParse(str, formatProvider) ?? throw new FormatException($"Invalid snowflake '{str}'.");
|
||||
public static Snowflake Parse(string value, IFormatProvider? formatProvider) =>
|
||||
TryParse(value, formatProvider)
|
||||
?? throw new FormatException($"Invalid snowflake '{value}'.");
|
||||
|
||||
public static Snowflake Parse(string str) => Parse(str, null);
|
||||
public static Snowflake Parse(string value) => Parse(value, null);
|
||||
}
|
||||
|
||||
public partial record struct Snowflake : IComparable<Snowflake>, IComparable
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AsyncKeyedLock" Version="6.2.2" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" PrivateAssets="all" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.2" PrivateAssets="all" />
|
||||
<PackageReference Include="Gress" Version="2.1.1" />
|
||||
<PackageReference Include="JsonExtensions" Version="1.2.0" />
|
||||
<PackageReference Include="Polly" Version="8.1.0" />
|
||||
<PackageReference Include="Polly" Version="8.2.0" />
|
||||
<PackageReference Include="RazorBlade" Version="0.4.4" />
|
||||
<PackageReference Include="Superpower" Version="3.0.0" />
|
||||
<PackageReference Include="WebMarkupMin.Core" Version="2.14.0" />
|
||||
|
||||
@@ -6,8 +6,12 @@ public class DiscordChatExporterException : Exception
|
||||
{
|
||||
public bool IsFatal { get; }
|
||||
|
||||
public DiscordChatExporterException(string message, bool isFatal = false)
|
||||
: base(message)
|
||||
public DiscordChatExporterException(
|
||||
string message,
|
||||
bool isFatal = false,
|
||||
Exception? innerException = null
|
||||
)
|
||||
: base(message, innerException)
|
||||
{
|
||||
IsFatal = isFatal;
|
||||
}
|
||||
|
||||
@@ -8,11 +8,9 @@ using Gress;
|
||||
|
||||
namespace DiscordChatExporter.Core.Exporting;
|
||||
|
||||
public class ChannelExporter
|
||||
public class ChannelExporter(DiscordClient discord)
|
||||
{
|
||||
private readonly DiscordClient _discord;
|
||||
|
||||
public ChannelExporter(DiscordClient discord) => _discord = discord;
|
||||
private readonly DiscordClient _discord = discord;
|
||||
|
||||
public async ValueTask ExportChannelAsync(
|
||||
ExportRequest request,
|
||||
@@ -24,7 +22,9 @@ public class ChannelExporter
|
||||
if (request.Channel.Kind == ChannelKind.GuildForum)
|
||||
{
|
||||
throw new DiscordChatExporterException(
|
||||
"Channel is a forum and cannot be exported directly. "
|
||||
$"Channel '{request.Channel.Name}' (#{request.Channel.Id}) "
|
||||
+ $"of guild '{request.Guild.Name}' (#{request.Guild.Id}) "
|
||||
+ $"is a forum and cannot be exported directly. "
|
||||
+ "You need to pull its threads and export them individually."
|
||||
);
|
||||
}
|
||||
@@ -32,14 +32,20 @@ public class ChannelExporter
|
||||
// Check if the channel is empty
|
||||
if (request.Channel.IsEmpty)
|
||||
{
|
||||
throw new DiscordChatExporterException("Channel does not contain any messages.");
|
||||
throw new DiscordChatExporterException(
|
||||
$"Channel '{request.Channel.Name}' (#{request.Channel.Id}) "
|
||||
+ $"of guild '{request.Guild.Name}' (#{request.Guild.Id}) "
|
||||
+ $"does not contain any messages."
|
||||
);
|
||||
}
|
||||
|
||||
// Check if the 'after' boundary is valid
|
||||
if (request.After is not null && !request.Channel.MayHaveMessagesAfter(request.After.Value))
|
||||
{
|
||||
throw new DiscordChatExporterException(
|
||||
"Channel does not contain any messages within the specified period."
|
||||
$"Channel '{request.Channel.Name}' (#{request.Channel.Id}) "
|
||||
+ $"of guild '{request.Guild.Name}' (#{request.Guild.Id}) "
|
||||
+ $"does not contain any messages within the specified period."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -50,7 +56,9 @@ public class ChannelExporter
|
||||
)
|
||||
{
|
||||
throw new DiscordChatExporterException(
|
||||
"Channel does not contain any messages within the specified period."
|
||||
$"Channel '{request.Channel.Name}' (#{request.Channel.Id}) "
|
||||
+ $"of guild '{request.Guild.Name}' (#{request.Guild.Id}) "
|
||||
+ $"does not contain any messages within the specified period."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -70,20 +78,36 @@ public class ChannelExporter
|
||||
)
|
||||
)
|
||||
{
|
||||
// Resolve members for referenced users
|
||||
foreach (var user in message.GetReferencedUsers())
|
||||
await context.PopulateMemberAsync(user, cancellationToken);
|
||||
try
|
||||
{
|
||||
// Resolve members for referenced users
|
||||
foreach (var user in message.GetReferencedUsers())
|
||||
await context.PopulateMemberAsync(user, cancellationToken);
|
||||
|
||||
// Export the message
|
||||
if (request.MessageFilter.IsMatch(message))
|
||||
await messageExporter.ExportMessageAsync(message, cancellationToken);
|
||||
// Export the message
|
||||
if (request.MessageFilter.IsMatch(message))
|
||||
await messageExporter.ExportMessageAsync(message, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Provide more context to the exception, to simplify debugging based on error messages
|
||||
throw new DiscordChatExporterException(
|
||||
$"Failed to export message #{message.Id} "
|
||||
+ $"in channel '{request.Channel.Name}' (#{request.Channel.Id}) "
|
||||
+ $"of guild '{request.Guild.Name} (#{request.Guild.Id})'.",
|
||||
ex is not DiscordChatExporterException dex || dex.IsFatal,
|
||||
ex
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Throw if no messages were exported
|
||||
if (messageExporter.MessagesExported <= 0)
|
||||
{
|
||||
throw new DiscordChatExporterException(
|
||||
"Channel does not contain any matching messages within the specified period."
|
||||
$"Channel '{request.Channel.Name}' (#{request.Channel.Id}) "
|
||||
+ $"of guild '{request.Guild.Name}' (#{request.Guild.Id}) "
|
||||
+ $"does not contain any matching messages within the specified period."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,15 +8,10 @@ using DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
namespace DiscordChatExporter.Core.Exporting;
|
||||
|
||||
internal partial class CsvMessageWriter : MessageWriter
|
||||
internal partial class CsvMessageWriter(Stream stream, ExportContext context)
|
||||
: MessageWriter(stream, context)
|
||||
{
|
||||
private readonly TextWriter _writer;
|
||||
|
||||
public CsvMessageWriter(Stream stream, ExportContext context)
|
||||
: base(stream, context)
|
||||
{
|
||||
_writer = new StreamWriter(stream);
|
||||
}
|
||||
private readonly TextWriter _writer = new StreamWriter(stream);
|
||||
|
||||
private async ValueTask<string> FormatMarkdownAsync(
|
||||
string markdown,
|
||||
|
||||
@@ -14,7 +14,7 @@ using DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
namespace DiscordChatExporter.Core.Exporting;
|
||||
|
||||
internal partial class ExportAssetDownloader
|
||||
internal partial class ExportAssetDownloader(string workingDirPath, bool reuse)
|
||||
{
|
||||
private static readonly AsyncKeyedLocker<string> Locker =
|
||||
new(o =>
|
||||
@@ -23,18 +23,12 @@ internal partial class ExportAssetDownloader
|
||||
o.PoolInitialFill = 1;
|
||||
});
|
||||
|
||||
private readonly string _workingDirPath;
|
||||
private readonly bool _reuse;
|
||||
private readonly string _workingDirPath = workingDirPath;
|
||||
private readonly bool _reuse = reuse;
|
||||
|
||||
// File paths of the previously downloaded assets
|
||||
private readonly Dictionary<string, string> _previousPathsByUrl = new(StringComparer.Ordinal);
|
||||
|
||||
public ExportAssetDownloader(string workingDirPath, bool reuse)
|
||||
{
|
||||
_workingDirPath = workingDirPath;
|
||||
_reuse = reuse;
|
||||
}
|
||||
|
||||
public async ValueTask<string> DownloadAsync(
|
||||
string url,
|
||||
CancellationToken cancellationToken = default
|
||||
|
||||
@@ -12,27 +12,18 @@ using DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
namespace DiscordChatExporter.Core.Exporting;
|
||||
|
||||
internal class ExportContext
|
||||
internal class ExportContext(DiscordClient discord, ExportRequest request)
|
||||
{
|
||||
private readonly Dictionary<Snowflake, Member?> _membersById = new();
|
||||
private readonly Dictionary<Snowflake, Channel> _channelsById = new();
|
||||
private readonly Dictionary<Snowflake, Role> _rolesById = new();
|
||||
private readonly ExportAssetDownloader _assetDownloader;
|
||||
|
||||
public DiscordClient Discord { get; }
|
||||
private readonly ExportAssetDownloader _assetDownloader =
|
||||
new(request.AssetsDirPath, request.ShouldReuseAssets);
|
||||
|
||||
public ExportRequest Request { get; }
|
||||
public DiscordClient Discord { get; } = discord;
|
||||
|
||||
public ExportContext(DiscordClient discord, ExportRequest request)
|
||||
{
|
||||
Discord = discord;
|
||||
Request = request;
|
||||
|
||||
_assetDownloader = new ExportAssetDownloader(
|
||||
request.AssetsDirPath,
|
||||
request.ShouldReuseAssets
|
||||
);
|
||||
}
|
||||
public ExportRequest Request { get; } = request;
|
||||
|
||||
public DateTimeOffset NormalizeDate(DateTimeOffset instant) =>
|
||||
Request.IsUtcNormalizationEnabled ? instant.ToUniversalTime() : instant.ToLocalTime();
|
||||
@@ -124,9 +115,9 @@ internal class ExportContext
|
||||
var filePath = await _assetDownloader.DownloadAsync(url, cancellationToken);
|
||||
var relativeFilePath = Path.GetRelativePath(Request.OutputDirPath, filePath);
|
||||
|
||||
// Prefer relative paths so that the output files can be copied around without breaking references.
|
||||
// If the asset directory is outside of the export directory, use an absolute path instead.
|
||||
var optimalFilePath =
|
||||
// Prefer the relative path so that the export package can be copied around without breaking references.
|
||||
// However, if the assets directory lies outside of the export directory, use the absolute path instead.
|
||||
var shouldUseAbsoluteFilePath =
|
||||
relativeFilePath.StartsWith(
|
||||
".." + Path.DirectorySeparatorChar,
|
||||
StringComparison.Ordinal
|
||||
@@ -134,15 +125,19 @@ internal class ExportContext
|
||||
|| relativeFilePath.StartsWith(
|
||||
".." + Path.AltDirectorySeparatorChar,
|
||||
StringComparison.Ordinal
|
||||
)
|
||||
? filePath
|
||||
: relativeFilePath;
|
||||
);
|
||||
|
||||
var optimalFilePath = shouldUseAbsoluteFilePath ? filePath : relativeFilePath;
|
||||
|
||||
// For HTML, the path needs to be properly formatted
|
||||
if (Request.Format is ExportFormat.HtmlDark or ExportFormat.HtmlLight)
|
||||
{
|
||||
// Create a 'file:///' URI and then strip the 'file:///' prefix to allow for relative paths
|
||||
return new Uri(new Uri("file:///"), optimalFilePath).ToString()[8..];
|
||||
// Format the path into a valid file URI
|
||||
var href = new Uri(new Uri("file:///"), optimalFilePath).ToString();
|
||||
|
||||
// File schema does not support relative paths, so strip it if that's the case
|
||||
// https://github.com/Tyrrrz/DiscordChatExporter/issues/1155
|
||||
return shouldUseAbsoluteFilePath ? href : href[8..];
|
||||
}
|
||||
|
||||
return optimalFilePath;
|
||||
|
||||
@@ -12,18 +12,15 @@ using DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
namespace DiscordChatExporter.Core.Exporting;
|
||||
|
||||
internal partial class HtmlMarkdownVisitor : MarkdownVisitor
|
||||
internal partial class HtmlMarkdownVisitor(
|
||||
ExportContext context,
|
||||
StringBuilder buffer,
|
||||
bool isJumbo
|
||||
) : MarkdownVisitor
|
||||
{
|
||||
private readonly ExportContext _context;
|
||||
private readonly StringBuilder _buffer;
|
||||
private readonly bool _isJumbo;
|
||||
|
||||
public HtmlMarkdownVisitor(ExportContext context, StringBuilder buffer, bool isJumbo)
|
||||
{
|
||||
_context = context;
|
||||
_buffer = buffer;
|
||||
_isJumbo = isJumbo;
|
||||
}
|
||||
private readonly ExportContext _context = context;
|
||||
private readonly StringBuilder _buffer = buffer;
|
||||
private readonly bool _isJumbo = isJumbo;
|
||||
|
||||
protected override ValueTask VisitTextAsync(
|
||||
TextNode text,
|
||||
|
||||
@@ -9,21 +9,15 @@ using WebMarkupMin.Core;
|
||||
|
||||
namespace DiscordChatExporter.Core.Exporting;
|
||||
|
||||
internal class HtmlMessageWriter : MessageWriter
|
||||
internal class HtmlMessageWriter(Stream stream, ExportContext context, string themeName)
|
||||
: MessageWriter(stream, context)
|
||||
{
|
||||
private readonly TextWriter _writer;
|
||||
private readonly string _themeName;
|
||||
private readonly TextWriter _writer = new StreamWriter(stream);
|
||||
private readonly string _themeName = themeName;
|
||||
|
||||
private readonly HtmlMinifier _minifier = new();
|
||||
private readonly List<Message> _messageGroup = new();
|
||||
|
||||
public HtmlMessageWriter(Stream stream, ExportContext context, string themeName)
|
||||
: base(stream, context)
|
||||
{
|
||||
_writer = new StreamWriter(stream);
|
||||
_themeName = themeName;
|
||||
}
|
||||
|
||||
private bool CanJoinGroup(Message message)
|
||||
{
|
||||
// If the group is empty, any message can join it
|
||||
|
||||
@@ -12,26 +12,21 @@ using JsonExtensions.Writing;
|
||||
|
||||
namespace DiscordChatExporter.Core.Exporting;
|
||||
|
||||
internal class JsonMessageWriter : MessageWriter
|
||||
internal class JsonMessageWriter(Stream stream, ExportContext context)
|
||||
: MessageWriter(stream, context)
|
||||
{
|
||||
private readonly Utf8JsonWriter _writer;
|
||||
|
||||
public JsonMessageWriter(Stream stream, ExportContext context)
|
||||
: base(stream, context)
|
||||
{
|
||||
_writer = new Utf8JsonWriter(
|
||||
stream,
|
||||
new JsonWriterOptions
|
||||
{
|
||||
// https://github.com/Tyrrrz/DiscordChatExporter/issues/450
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
Indented = true,
|
||||
// Validation errors may mask actual failures
|
||||
// https://github.com/Tyrrrz/DiscordChatExporter/issues/413
|
||||
SkipValidation = true
|
||||
}
|
||||
);
|
||||
}
|
||||
private readonly Utf8JsonWriter _writer = new Utf8JsonWriter(
|
||||
stream,
|
||||
new JsonWriterOptions
|
||||
{
|
||||
// https://github.com/Tyrrrz/DiscordChatExporter/issues/450
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
Indented = true,
|
||||
// Validation errors may mask actual failures
|
||||
// https://github.com/Tyrrrz/DiscordChatExporter/issues/413
|
||||
SkipValidation = true
|
||||
}
|
||||
);
|
||||
|
||||
private async ValueTask<string> FormatMarkdownAsync(
|
||||
string markdown,
|
||||
|
||||
@@ -6,20 +6,15 @@ using DiscordChatExporter.Core.Discord.Data;
|
||||
|
||||
namespace DiscordChatExporter.Core.Exporting;
|
||||
|
||||
internal partial class MessageExporter : IAsyncDisposable
|
||||
internal partial class MessageExporter(ExportContext context) : IAsyncDisposable
|
||||
{
|
||||
private readonly ExportContext _context;
|
||||
private readonly ExportContext _context = context;
|
||||
|
||||
private int _partitionIndex;
|
||||
private MessageWriter? _writer;
|
||||
|
||||
public long MessagesExported { get; private set; }
|
||||
|
||||
public MessageExporter(ExportContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
private async ValueTask ResetWriterAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (_writer is not null)
|
||||
|
||||
@@ -6,22 +6,16 @@ using DiscordChatExporter.Core.Discord.Data;
|
||||
|
||||
namespace DiscordChatExporter.Core.Exporting;
|
||||
|
||||
internal abstract class MessageWriter : IAsyncDisposable
|
||||
internal abstract class MessageWriter(Stream stream, ExportContext context) : IAsyncDisposable
|
||||
{
|
||||
protected Stream Stream { get; }
|
||||
protected Stream Stream { get; } = stream;
|
||||
|
||||
protected ExportContext Context { get; }
|
||||
protected ExportContext Context { get; } = context;
|
||||
|
||||
public long MessagesWritten { get; private set; }
|
||||
|
||||
public long BytesWritten => Stream.Length;
|
||||
|
||||
protected MessageWriter(Stream stream, ExportContext context)
|
||||
{
|
||||
Stream = stream;
|
||||
Context = context;
|
||||
}
|
||||
|
||||
public virtual ValueTask WritePreambleAsync(CancellationToken cancellationToken = default) =>
|
||||
default;
|
||||
|
||||
|
||||
@@ -8,16 +8,11 @@ using DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
namespace DiscordChatExporter.Core.Exporting;
|
||||
|
||||
internal partial class PlainTextMarkdownVisitor : MarkdownVisitor
|
||||
internal partial class PlainTextMarkdownVisitor(ExportContext context, StringBuilder buffer)
|
||||
: MarkdownVisitor
|
||||
{
|
||||
private readonly ExportContext _context;
|
||||
private readonly StringBuilder _buffer;
|
||||
|
||||
public PlainTextMarkdownVisitor(ExportContext context, StringBuilder buffer)
|
||||
{
|
||||
_context = context;
|
||||
_buffer = buffer;
|
||||
}
|
||||
private readonly ExportContext _context = context;
|
||||
private readonly StringBuilder _buffer = buffer;
|
||||
|
||||
protected override ValueTask VisitTextAsync(
|
||||
TextNode text,
|
||||
|
||||
@@ -8,15 +8,10 @@ using DiscordChatExporter.Core.Discord.Data.Embeds;
|
||||
|
||||
namespace DiscordChatExporter.Core.Exporting;
|
||||
|
||||
internal class PlainTextMessageWriter : MessageWriter
|
||||
internal class PlainTextMessageWriter(Stream stream, ExportContext context)
|
||||
: MessageWriter(stream, context)
|
||||
{
|
||||
private readonly TextWriter _writer;
|
||||
|
||||
public PlainTextMessageWriter(Stream stream, ExportContext context)
|
||||
: base(stream, context)
|
||||
{
|
||||
_writer = new StreamWriter(stream);
|
||||
}
|
||||
private readonly TextWriter _writer = new StreamWriter(stream);
|
||||
|
||||
private async ValueTask<string> FormatMarkdownAsync(
|
||||
string markdown,
|
||||
|
||||
@@ -340,13 +340,27 @@ internal static partial class MarkdownParser
|
||||
)
|
||||
);
|
||||
|
||||
// https://discord.com/developers/docs/reference#message-formatting-timestamp-styles
|
||||
var format = m.Groups[2].Value.NullIfWhiteSpace() switch
|
||||
{
|
||||
// Ignore the 'relative' format because it doesn't make sense in a static export
|
||||
// Known formats
|
||||
"t" => "t",
|
||||
"T" => "T",
|
||||
"d" => "d",
|
||||
"D" => "D",
|
||||
"f" => "f",
|
||||
"F" => "F",
|
||||
// Relative format: ignore because it doesn't make sense in a static export
|
||||
"r" => null,
|
||||
"R" => null,
|
||||
// Discord's date formats are (mostly) compatible with .NET's date formats
|
||||
var f => f
|
||||
// Unspecified format: will be mapped to the default format
|
||||
null => null,
|
||||
// Unknown format: throw an exception to consider this timestamp invalid
|
||||
// https://github.com/Tyrrrz/DiscordChatExporter/issues/1156
|
||||
var f
|
||||
=> throw new InvalidOperationException(
|
||||
$"Unknown timestamp format '{f}'."
|
||||
)
|
||||
};
|
||||
|
||||
return new TimestampNode(instant, format);
|
||||
@@ -354,7 +368,12 @@ internal static partial class MarkdownParser
|
||||
// https://github.com/Tyrrrz/DiscordChatExporter/issues/681
|
||||
// https://github.com/Tyrrrz/DiscordChatExporter/issues/766
|
||||
catch (Exception ex)
|
||||
when (ex is FormatException or ArgumentOutOfRangeException or OverflowException)
|
||||
when (ex
|
||||
is FormatException
|
||||
or ArgumentOutOfRangeException
|
||||
or OverflowException
|
||||
or InvalidOperationException
|
||||
)
|
||||
{
|
||||
// For invalid timestamps, Discord renders "Invalid Date" instead of ignoring the markdown
|
||||
return TimestampNode.Invalid;
|
||||
|
||||
@@ -27,7 +27,4 @@ public static class PathEx
|
||||
|
||||
return buffer.ToString();
|
||||
}
|
||||
|
||||
public static bool IsDirectoryPath(string path) =>
|
||||
path.EndsWith(Path.DirectorySeparatorChar) || path.EndsWith(Path.AltDirectorySeparatorChar);
|
||||
}
|
||||
|
||||
@@ -14,14 +14,13 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Cogwheel" Version="2.0.4" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" PrivateAssets="all" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.2" PrivateAssets="all" />
|
||||
<PackageReference Include="Deorcify" Version="1.0.2" PrivateAssets="all" />
|
||||
<PackageReference Include="DotnetRuntimeBootstrapper" Version="2.5.1" PrivateAssets="all" />
|
||||
<PackageReference Include="Gress" Version="2.1.1" />
|
||||
<PackageReference Include="MaterialDesignColors" Version="2.1.4" />
|
||||
<PackageReference Include="MaterialDesignThemes" Version="4.9.0" />
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.77" />
|
||||
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
|
||||
<PackageReference Include="Onova" Version="2.6.10" />
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Stylet" Version="1.3.6" />
|
||||
|
||||
@@ -277,9 +277,7 @@ public class DashboardViewModel : PropertyChangedBase
|
||||
}
|
||||
catch (DiscordChatExporterException ex) when (!ex.IsFatal)
|
||||
{
|
||||
_eventAggregator.Publish(
|
||||
new NotificationMessage(ex.Message.TrimEnd('.') + $" ({channel.Name})")
|
||||
);
|
||||
_eventAggregator.Publish(new NotificationMessage(ex.Message.TrimEnd('.')));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using Microsoft.Win32;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
using Stylet;
|
||||
|
||||
namespace DiscordChatExporter.Gui.ViewModels.Framework;
|
||||
@@ -68,9 +67,8 @@ public class DialogManager : IDisposable
|
||||
|
||||
public string? PromptDirectoryPath(string defaultDirPath = "")
|
||||
{
|
||||
var dialog = new VistaFolderBrowserDialog { SelectedPath = defaultDirPath };
|
||||
|
||||
return dialog.ShowDialog() == true ? dialog.SelectedPath : null;
|
||||
var dialog = new OpenFolderDialog { InitialDirectory = defaultDirPath };
|
||||
return dialog.ShowDialog() == true ? dialog.FolderName : null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -193,9 +193,8 @@
|
||||
<LineBreak />
|
||||
<Run Text="6. Switch between random channels to trigger network requests" />
|
||||
<LineBreak />
|
||||
<Run Text="7. Search for a request containing" />
|
||||
<Run FontWeight="SemiBold" Text="messages?limit=50" />
|
||||
<Run Text="or similar" />
|
||||
<Run Text="7. Search for a request that starts with" />
|
||||
<Run FontWeight="SemiBold" Text="messages" />
|
||||
<LineBreak />
|
||||
<Run Text="8. Select the" />
|
||||
<Run FontWeight="SemiBold" Text="Headers" />
|
||||
|
||||
@@ -271,7 +271,10 @@
|
||||
</Grid>
|
||||
|
||||
<!-- Reuse assets -->
|
||||
<Grid Margin="16,8" ToolTip="Reuse previously downloaded assets to avoid redundant requests">
|
||||
<Grid
|
||||
Margin="16,8"
|
||||
IsEnabled="{Binding ShouldDownloadAssets}"
|
||||
ToolTip="Reuse previously downloaded assets to avoid redundant requests">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
@@ -289,14 +292,16 @@
|
||||
</Grid>
|
||||
|
||||
<!-- Assets path -->
|
||||
<Grid Margin="16,8">
|
||||
<Grid
|
||||
Margin="16,8"
|
||||
IsEnabled="{Binding ShouldDownloadAssets}"
|
||||
ToolTip="Download assets to this directory. If not specified, the asset directory path will be derived from the output path.">
|
||||
<TextBox
|
||||
Padding="16,16,42,16"
|
||||
materialDesign:HintAssist.Hint="Assets directory path"
|
||||
materialDesign:HintAssist.IsFloating="True"
|
||||
Style="{DynamicResource MaterialDesignOutlinedTextBox}"
|
||||
Text="{Binding AssetsDirPath}"
|
||||
ToolTip="Download assets to this directory. If not specified, the asset directory path will be derived from the output path." />
|
||||
Text="{Binding AssetsDirPath}" />
|
||||
<Button
|
||||
Width="24"
|
||||
Height="24"
|
||||
|
||||
@@ -89,21 +89,21 @@ The following table lists all available download options:
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
> **Note**:
|
||||
> AUR and Nix packages linked above are maintained by the community.
|
||||
> If you have any issues with them, please contact the corresponding maintainers.
|
||||
|
||||
> **Warning**:
|
||||
> To run **DiscordChatExporter** on macOS and Linux, you need to make sure that **.NET 7.0 Runtime** is installed.
|
||||
> **Important**:
|
||||
> To run **DiscordChatExporter** on macOS and Linux, you need to make sure that **.NET 8.0 Runtime** is installed.
|
||||
> You can download it here:
|
||||
>
|
||||
> - [.NET 7.0 Runtime for **macOS x64**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/sdk-7.0.101-macos-x64-installer)
|
||||
> - [.NET 7.0 Runtime for **macOS Arm64**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/sdk-7.0.101-macos-arm64-installer)
|
||||
> - [.NET 7.0 Runtime for **Linux**](https://docs.microsoft.com/en-us/dotnet/core/install/linux) (find the correct download for your distro)
|
||||
> - [.NET 8.0 Runtime for **macOS x64**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.0-macos-x64-installer)
|
||||
> - [.NET 8.0 Runtime for **macOS arm64**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.0-macos-arm64-installer)
|
||||
> - [.NET 8.0 Runtime for **Linux**](https://learn.microsoft.com/dotnet/core/install/linux) (find the correct download for your distro)
|
||||
>
|
||||
> This should not be necessary if you install **DiscordChatExporter** using a package manager, as it should take care of the dependencies for you.
|
||||
> This is also not necessary if you are running **DiscordChatExporter** via Docker, because the image already contains the runtime.
|
||||
|
||||
> **Note**:
|
||||
> AUR and Nix packages linked above are maintained by the community.
|
||||
> If you have any issues with them, please contact the corresponding maintainers.
|
||||
|
||||
## Features
|
||||
|
||||
- Graphical user interface (Windows)
|
||||
@@ -119,7 +119,7 @@ The following table lists all available download options:
|
||||

|
||||

|
||||
|
||||
## Related projects
|
||||
## See also
|
||||
|
||||
- [**Chat Analytics**](https://github.com/mlomb/chat-analytics) — solution for analyzing chat patterns of Discord users, using exports produced by **DiscordChatExporter**.
|
||||
- [**DiscordChatExporter-frontend**](https://github.com/slatinsky/DiscordChatExporter-frontend) — convenient viewer for exports produced by **DiscordChatExporter**.
|
||||
Reference in New Issue
Block a user