mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-07-07 14:44:39 +02:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a46bf9bf11 | |||
| 8dc024d244 | |||
| 9a125db0ea | |||
| d9c35f4405 | |||
| 5846129cc6 | |||
| 6f5f747632 | |||
| 6a71c59b6d | |||
| 73574ade48 | |||
| 743db67f91 | |||
| 5d7a74eece | |||
| 129df42de4 | |||
| 6508455f3a | |||
| 50b26c557f | |||
| b709fc0f15 | |||
| c118a0bb94 | |||
| 1418bec0c7 | |||
| 750fd69a50 | |||
| b1297bb7df | |||
| 3189111a0e | |||
| 6ec2c04aa3 | |||
| 7c014bf64d | |||
| c875f8f4f0 | |||
| 69e2c337d8 | |||
| 77c770acdd | |||
| 6f8749a105 | |||
| 4896d748aa | |||
| 4876ed192a | |||
| 4f6e6f4f0b | |||
| 8c75f04115 | |||
| df04b123cd | |||
| 578ed9be17 | |||
| ebceacc707 | |||
| eaab5786f2 | |||
| ebf7d65334 | |||
| 52a23828ce | |||
| 2edd781e32 | |||
| 19cdf47c6e | |||
| 65e0a63bda | |||
| 692438d10c | |||
| c607c6f307 | |||
| aae43821e7 | |||
| 7b9a4e1aff | |||
| d8e57f94a8 | |||
| 7b7df564ed | |||
| 80b59d1254 | |||
| 6579563816 | |||
| e2971ed3a6 | |||
| a0a263f074 | |||
| 1438fd9f77 | |||
| b298b45cf7 | |||
| 8d01c6be35 |
+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
|
||||
|
||||
|
||||
+9
-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
|
||||
|
||||
@@ -15,6 +15,12 @@ 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).
|
||||
If the above command throws a "Permission denied" error, execute this command to fix the permissions:
|
||||
|
||||
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.
|
||||
```console
|
||||
chmod 644 *.dll DiscordChatExporter.*
|
||||
```
|
||||
|
||||
> [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](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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
+130
-110
@@ -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,22 +34,23 @@ 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](#export) | Exports a channel |
|
||||
| [exportdm](#exportdm) | Exports all direct message channels |
|
||||
| [exportguild](#exportguild) | Exports all channels within the specified server |
|
||||
| [exportall](#exportall) | Exports all accessible channels |
|
||||
| [channels](#channels) | Outputs the list of channels in the given server |
|
||||
| [dm](#dm) | Outputs the list of direct message channels |
|
||||
| [guilds](#guilds) | Outputs the list of accessible servers |
|
||||
| [guide](#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 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, please run:
|
||||
|
||||
```console
|
||||
@@ -59,21 +61,21 @@ dotnet DiscordChatExporter.Cli.dll command -h
|
||||
|
||||
With this command, you can export **server channels** and **direct messages**.
|
||||
|
||||
| | 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 |
|
||||
| | Option | Description |
|
||||
|--------|---------------------------------------|----------------------------------------------------------------------------------------------------------------|
|
||||
| **\*** | [-c](#basic-usage) | [Channel ID(s)](Token-and-IDs.md#how-to-get-guild-id-or-guild-channel-id) |
|
||||
| **\*** | [-t](#basic-usage) | [Authorization token](Token-and-IDs.md#how-to-get-user-token). Environment variable: `DISCORD_TOKEN` |
|
||||
| | [-o](#changing-the-output-filename) | Output file or directory path |
|
||||
| | [-f](#changing-the-format) | [Output file format](Getting-started.md#file-formats). Default: HtmlDark |
|
||||
| | [--after](#date-ranges) | Only include messages sent after this date |
|
||||
| | [--before](#date-ranges) | Only include messages sent before this date |
|
||||
| | [-p](#partitioning) | Split output into partitions, each limited to this number of messages (e.g. 100) or file size (e.g. 10mb) |
|
||||
| | [--filter](Message-filters.md) | Special notation for filtering the messages that get included in the export |
|
||||
| | [--media](#downloading-assets) | Download assets referenced by the export (user avatars, attached files, embedded images, etc.). Default: false |
|
||||
| | [--reuse-media](#reuse-assets) | Reuse previously downloaded assets to avoid redundant requests. Default: false |
|
||||
| | [--media-dir](#downloading-assets) | Directory to store assets from all exported channels in the same place |
|
||||
| | [--locale](#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.
|
||||
@@ -88,7 +90,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 +107,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 +133,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 +169,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 +179,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 +188,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 +197,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,35 +221,38 @@ 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`
|
||||
|
||||
This command exports all your **direct messages**.
|
||||
|
||||
| | 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 |
|
||||
| | Option | Description |
|
||||
|--------|---------------------------------------|----------------------------------------------------------------------------------------------------------------|
|
||||
| **\*** | [-c](#basic-usage) | [Channel ID(s)](Token-and-IDs.md#how-to-get-guild-id-or-guild-channel-id) |
|
||||
| **\*** | [-t](#basic-usage) | [Authorization token](Token-and-IDs.md#how-to-get-user-token). Environment variable: `DISCORD_TOKEN` |
|
||||
| | [-o](#changing-the-output-filename) | Output file or directory path |
|
||||
| | [-f](#changing-the-format) | [Output file format](Getting-started.md#file-formats). Default: HtmlDark |
|
||||
| | [--after](#date-ranges) | Only include messages sent after this date |
|
||||
| | [--before](#date-ranges) | Only include messages sent before this date |
|
||||
| | [-p](#partitioning) | Split output into partitions, each limited to this number of messages (e.g. 100) or file size (e.g. 10mb) |
|
||||
| | [--filter](Message-filters.md) | Special notation for filtering the messages that get included in the export |
|
||||
| | [--media](#downloading-assets) | Download assets referenced by the export (user avatars, attached files, embedded images, etc.). Default: false |
|
||||
| | [--reuse-media](#reuse-assets) | Reuse previously downloaded assets to avoid redundant requests. Default: false |
|
||||
| | [--media-dir](#downloading-assets) | Directory to store assets from all exported channels in the same place |
|
||||
| | [--locale](#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.
|
||||
@@ -248,30 +261,32 @@ This command exports all your **direct messages**.
|
||||
|
||||
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 |
|
||||
| | Option | Description |
|
||||
|--------|-------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **\*** | -g | [Server ID](Token-and-IDs.md#how-to-get-guild-id-or-guild-channel-id) |
|
||||
| **\*** | [-t](#basic-usage) | [Authorization token](Token-and-IDs.md#how-to-get-user-token). Environment variable: `DISCORD_TOKEN` |
|
||||
| | [-o](#changing-the-output-filename) | Output file or directory path |
|
||||
| | [-f](#changing-the-format) | [Output file format](Getting-started.md#file-formats). Default: HtmlDark |
|
||||
| | [--after](#date-ranges) | Only include messages sent after this date |
|
||||
| | [--before](#date-ranges) | Only include messages sent before this date |
|
||||
| | [-p](#partitioning) | Split output into partitions, each limited to this number of messages (e.g. 100) or file size (e.g. 10mb) |
|
||||
| | [--filter](Message-filters.md) | Special notation for filtering the messages that get included in the export |
|
||||
| | [--media](#downloading-assets) | Download assets referenced by the export (user avatars, attached files, embedded images, etc.). Default: false |
|
||||
| | [--reuse-media](#reuse-assets) | Reuse previously downloaded assets to avoid redundant requests. Default: false |
|
||||
| | [--media-dir](#downloading-assets) | Directory to store assets from all exported channels in the same place |
|
||||
| | [--locale](#changing-the-date-format) | Format used when writing dates. Default: en-US |
|
||||
| | [--include-threads](#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](#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.
|
||||
|
||||
#### 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,7 +294,9 @@ 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
|
||||
@@ -289,23 +306,23 @@ dotnet DiscordChatExporter.Cli.dll exportguild -t "mfa.Ifrn" -g 21814 --include-
|
||||
|
||||
This command exports **all accessible channels**, including server channels and DMs.
|
||||
|
||||
| | 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 |
|
||||
| | Option | Description |
|
||||
|--------|-------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **\*** | [-t](#basic-usage) | [Authorization token](Token-and-IDs.md#how-to-get-user-token). Environment variable: `DISCORD_TOKEN` |
|
||||
| | [-o](#changing-the-output-filename) | Output file or directory path |
|
||||
| | [-f](#changing-the-format) | [Output file format](Getting-started.md#file-formats). Default: HtmlDark |
|
||||
| | [--after](#date-ranges) | Only include messages sent after this date |
|
||||
| | [--before](#date-ranges) | Only include messages sent before this date |
|
||||
| | [-p](#partitioning) | Split output into partitions, each limited to this number of messages (e.g. 100) or file size (e.g. 10mb) |
|
||||
| | [--filter](Message-filters.md) | Special notation for filtering the messages that get included in the export |
|
||||
| | [--media](#downloading-assets) | Download assets referenced by the export (user avatars, attached files, embedded images, etc.). Default: false |
|
||||
| | [--reuse-media](#reuse-assets) | Reuse previously downloaded assets to avoid redundant requests. Default: false |
|
||||
| | [--media-dir](#downloading-assets) | Directory to store assets from all exported channels in the same place |
|
||||
| | [--locale](#changing-the-date-format) | Format used when writing dates. Default: en-US |
|
||||
| | [--include-threads](#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](#including-voice-channels) | Include voice channels in the export. Default: true |
|
||||
| | [--include-dm](#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.
|
||||
@@ -324,18 +341,19 @@ 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 |
|
||||
| | Option | Description |
|
||||
|--------|-------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **\*** | -g | [Server ID](Token-and-IDs.md#how-to-get-guild-id-or-guild-channel-id) |
|
||||
| **\*** | [-t](#basic-usage) | [Authorization token](Token-and-IDs.md#how-to-get-user-token). Environment variable: `DISCORD_TOKEN` |
|
||||
| | [--include-threads](#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](#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 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.
|
||||
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll channels -t "mfa.Ifrn" -g 21814 > C:\path\to\output.txt
|
||||
@@ -345,15 +363,16 @@ dotnet DiscordChatExporter.Cli.dll channels -t "mfa.Ifrn" -g 21814 > C:\path\to\
|
||||
|
||||
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 |
|
||||
| | Option | Description |
|
||||
|--------|--------------------|------------------------------------------------------------------------------------------------------|
|
||||
| **\*** | [-t](#basic-usage) | [Authorization token](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 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.
|
||||
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll dm -t "mfa.Ifrn" > C:\path\to\output.txt
|
||||
@@ -363,15 +382,16 @@ dotnet DiscordChatExporter.Cli.dll dm -t "mfa.Ifrn" > C:\path\to\output.txt
|
||||
|
||||
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 |
|
||||
| | Option | Description |
|
||||
|--------|--------------------|------------------------------------------------------------------------------------------------------|
|
||||
| **\*** | [-t](#basic-usage) | [Authorization token](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 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.
|
||||
|
||||
```console
|
||||
dotnet DiscordChatExporter.Cli.dll guilds -t "mfa.Ifrn" > C:\path\to\output.txt
|
||||
@@ -379,4 +399,4 @@ 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).
|
||||
This command explains [how to get your token, guild, and channel IDs](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,8 +1,12 @@
|
||||
name: docker
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
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:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
@@ -18,20 +22,21 @@ 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
|
||||
with:
|
||||
name: DiscordChatExporter.Cli.Docker
|
||||
path: DiscordChatExporter.Cli.Docker.tar
|
||||
if-no-files-found: error
|
||||
|
||||
deploy-latest:
|
||||
if: ${{ github.event_name == 'push' && github.ref_type == 'branch' && github.ref_name == 'master' }}
|
||||
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') }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -50,37 +55,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
|
||||
.
|
||||
|
||||
deploy-stable:
|
||||
if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # 4.1.0
|
||||
|
||||
- name: Install Docker Buildx
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # 3.0.0
|
||||
|
||||
- name: Login to DockerHub
|
||||
run: >
|
||||
echo ${{ secrets.DOCKER_TOKEN }} |
|
||||
docker login --username tyrrrz --password-stdin
|
||||
|
||||
- name: Build & push image
|
||||
run: >
|
||||
docker buildx build
|
||||
--file DiscordChatExporter.Cli.dockerfile
|
||||
--platform linux/amd64,linux/arm64
|
||||
--push
|
||||
--tag tyrrrz/discordchatexporter:stable
|
||||
--tag tyrrrz/discordchatexporter:${{ github.ref_name }}
|
||||
.
|
||||
${{ github.ref_type == 'tag' && '--tag tyrrrz/discordchatexporter:$GITHUB_REF_NAME' || '' }}
|
||||
${{ github.ref_type == 'tag' && '--tag tyrrrz/discordchatexporter:stable' || '' }}
|
||||
|
||||
+65
-57
@@ -1,6 +1,8 @@
|
||||
name: main
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
|
||||
@@ -20,11 +22,13 @@ jobs:
|
||||
- name: Install .NET
|
||||
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # 3.2.0
|
||||
with:
|
||||
dotnet-version: 7.0.x
|
||||
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
|
||||
--configuration Release
|
||||
@@ -33,8 +37,6 @@ jobs:
|
||||
--
|
||||
RunConfiguration.CollectSourceInformation=true
|
||||
DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover
|
||||
env:
|
||||
DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }}
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # 3.1.4
|
||||
@@ -42,6 +44,12 @@ jobs:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
pack:
|
||||
strategy:
|
||||
matrix:
|
||||
app:
|
||||
- DiscordChatExporter.Cli
|
||||
- DiscordChatExporter.Gui
|
||||
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
actions: write
|
||||
@@ -54,82 +62,82 @@ 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 (CLI)
|
||||
- name: Publish app
|
||||
run: >
|
||||
dotnet publish DiscordChatExporter.Cli
|
||||
--output DiscordChatExporter.Cli/publish/
|
||||
dotnet publish ${{ matrix.app }}
|
||||
--output ${{ matrix.app }}/bin/publish/
|
||||
--configuration Release
|
||||
|
||||
- name: Publish (GUI)
|
||||
run: >
|
||||
dotnet publish DiscordChatExporter.Gui
|
||||
--output DiscordChatExporter.Gui/publish/
|
||||
--configuration Release
|
||||
|
||||
- name: Upload artifacts (CLI)
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # 3.1.3
|
||||
with:
|
||||
name: DiscordChatExporter.Cli
|
||||
path: DiscordChatExporter.Cli/publish/
|
||||
name: ${{ matrix.app }}
|
||||
path: ${{ matrix.app }}/bin/publish/
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload artifacts (GUI)
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # 3.1.3
|
||||
with:
|
||||
name: DiscordChatExporter
|
||||
path: DiscordChatExporter.Gui/publish/
|
||||
|
||||
deploy:
|
||||
release:
|
||||
if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }}
|
||||
|
||||
needs:
|
||||
- test
|
||||
- pack
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Create release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: >
|
||||
gh release create ${{ github.ref_name }}
|
||||
--repo ${{ github.event.repository.full_name }}
|
||||
--title ${{ github.ref_name }}
|
||||
--notes "[Changelog](${{ github.event.repository.html_url }}/blob/${{ github.ref_name }}/Changelog.md)"
|
||||
--verify-tag
|
||||
|
||||
deploy:
|
||||
needs: release
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
app:
|
||||
- DiscordChatExporter.Cli
|
||||
- DiscordChatExporter.Gui
|
||||
include:
|
||||
- app: DiscordChatExporter.Cli
|
||||
asset: DiscordChatExporter.Cli
|
||||
- app: DiscordChatExporter.Gui
|
||||
# GUI asset isn't suffixed, unlike the CLI asset
|
||||
asset: DiscordChatExporter
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Download artifacts (CLI)
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # 3.0.2
|
||||
with:
|
||||
name: DiscordChatExporter.Cli
|
||||
path: DiscordChatExporter.Cli
|
||||
name: ${{ matrix.app }}
|
||||
path: ${{ matrix.app }}/
|
||||
|
||||
- name: Download artifacts (GUI)
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # 3.0.2
|
||||
with:
|
||||
name: DiscordChatExporter
|
||||
path: DiscordChatExporter.Gui
|
||||
- name: Create package
|
||||
# Change into the artifacts directory to avoid including the directory itself in the zip archive
|
||||
working-directory: ${{ matrix.app }}/
|
||||
run: zip -r ../${{ matrix.asset }}.zip .
|
||||
|
||||
- name: Create package (CLI)
|
||||
shell: pwsh
|
||||
run: >
|
||||
Compress-Archive
|
||||
-Path DiscordChatExporter.Cli/*
|
||||
-DestinationPath DiscordChatExporter.Cli.zip
|
||||
-Force
|
||||
|
||||
- name: Create package (GUI)
|
||||
shell: pwsh
|
||||
run: >
|
||||
Compress-Archive
|
||||
-Path DiscordChatExporter.Gui/*
|
||||
-DestinationPath DiscordChatExporter.zip
|
||||
-Force
|
||||
|
||||
- name: Create release
|
||||
- name: Upload release asset
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: >
|
||||
gh release create "${{ github.ref_name }}"
|
||||
"DiscordChatExporter.Cli.zip"
|
||||
"DiscordChatExporter.zip"
|
||||
--repo "${{ github.event.repository.full_name }}"
|
||||
--title "${{ github.ref_name }}"
|
||||
--notes "[Changelog](${{ github.event.repository.html_url }}/blob/${{ github.ref_name }}/Changelog.md)"
|
||||
--verify-tag
|
||||
gh release upload ${{ github.ref_name }}
|
||||
${{ matrix.asset }}.zip
|
||||
--repo ${{ github.event.repository.full_name }}
|
||||
|
||||
notify:
|
||||
needs: deploy
|
||||
@@ -148,6 +156,6 @@ jobs:
|
||||
body: |
|
||||
{
|
||||
"avatar_url": "https://raw.githubusercontent.com/${{ github.event.repository.full_name }}/${{ github.ref_name }}/favicon.png",
|
||||
"content": "**${{ github.event.repository.name }}** new version released!\nVersion: `${{ github.ref_name }}`\nDownload: <${{ github.event.repository.html_url }}/releases/tag/${{ github.ref_name }}>\nChangelog: <${{ github.event.repository.html_url }}/blob/${{ github.ref_name }}/Changelog.md>"
|
||||
"content": "**${{ github.event.repository.name }}** v${{ github.ref_name }} has been released!\n🔗 [Download](<${{ github.event.repository.html_url }}/releases/tag/${{ github.ref_name }}>) • [Changelog](<${{ github.event.repository.html_url }}/blob/${{ github.ref_name }}/Changelog.md>)"
|
||||
}
|
||||
retry-count: 5
|
||||
|
||||
+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,35 @@
|
||||
# Changelog
|
||||
|
||||
## 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:
|
||||
- Added the `video` field to the embed object, which may contain additional information about an embedded video resource.
|
||||
- CSV changes:
|
||||
- Fixed an issue where the `Date` field was incorrectly formatted. Now, the dates follow the `ISO 8601` standard.
|
||||
|
||||
## v2.42.2 (26-Oct-2023)
|
||||
|
||||
- General changes:
|
||||
- Fixed an issue where trying to export a channel that contained application interactions with empty command names crashed the application.
|
||||
|
||||
## v2.42.1 (19-Oct-2023)
|
||||
|
||||
- General changes:
|
||||
- Improved the error message shown when trying to export a forum channel. Such channels cannot be exported directly, you need to fetch and export their individual threads instead.
|
||||
- CLI changes:
|
||||
- Fixed an issue where fetching threads with `[` or `]` in their name crashed the application.
|
||||
|
||||
## v2.42 (12-Oct-2023)
|
||||
|
||||
- General changes:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Version>2.42</Version>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Version>2.42.4</Version>
|
||||
<Company>Tyrrrz</Company>
|
||||
<Copyright>Copyright (c) Oleksii Holub</Copyright>
|
||||
<LangVersion>preview</LangVersion>
|
||||
|
||||
@@ -11,19 +11,19 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AngleSharp" Version="1.0.4" />
|
||||
<PackageReference Include="AngleSharp" Version="1.0.6" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" PrivateAssets="all" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.25.0" PrivateAssets="all" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" 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.NET.Test.Sdk" Version="17.7.2" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="ReflectionMagic" Version="5.0.0" />
|
||||
<PackageReference Include="xunit" Version="2.5.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.1" PrivateAssets="all" />
|
||||
<PackageReference Include="xunit" Version="2.6.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -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 /build
|
||||
WORKDIR /tmp/app
|
||||
|
||||
COPY favicon.ico .
|
||||
COPY NuGet.config .
|
||||
@@ -22,25 +17,40 @@ COPY DiscordChatExporter.Cli DiscordChatExporter.Cli
|
||||
|
||||
# Publish a self-contained assembly so we can use a slimmer runtime image
|
||||
RUN dotnet publish DiscordChatExporter.Cli \
|
||||
--configuration Release \
|
||||
-p:CSharpier_Bypass=true \
|
||||
--configuration Release \
|
||||
--self-contained \
|
||||
--use-current-runtime \
|
||||
--arch $TARGETARCH \
|
||||
--output publish/
|
||||
--output DiscordChatExporter.Cli/bin/publish/
|
||||
|
||||
# -- 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
|
||||
|
||||
# Create a non-root user to run the app, so that the output files can be accessed by the host
|
||||
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."
|
||||
LABEL org.opencontainers.image.authors="tyrrrz.me"
|
||||
LABEL org.opencontainers.image.url="https://github.com/Tyrrrz/DiscordChatExporter"
|
||||
LABEL org.opencontainers.image.source="https://github.com/Tyrrrz/DiscordChatExporter/blob/master/DiscordChatExporter.Cli.dockerfile"
|
||||
LABEL org.opencontainers.image.licenses="MIT"
|
||||
|
||||
# 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 /build/publish /opt/dce
|
||||
ENTRYPOINT ["/opt/dce/DiscordChatExporter.Cli"]
|
||||
COPY --from=build /tmp/app/DiscordChatExporter.Cli/bin/publish /opt/app
|
||||
ENTRYPOINT ["/opt/app/DiscordChatExporter.Cli"]
|
||||
@@ -37,15 +37,28 @@ public abstract class DiscordCommandBase : ICommand
|
||||
{
|
||||
using (console.WithForegroundColor(ConsoleColor.DarkYellow))
|
||||
{
|
||||
console.Error.WriteLine(
|
||||
"Warning: Option --bot is deprecated and should not be used. "
|
||||
+ "The type of the provided token is now inferred automatically. "
|
||||
+ "Please update your workflows as this option may be completely removed in a future version."
|
||||
);
|
||||
console
|
||||
.Error
|
||||
.WriteLine(
|
||||
"Warning: Option --bot is deprecated and should not be used. "
|
||||
+ "The type of the provided token is now inferred automatically. "
|
||||
+ "Please update your workflows as this option may be completely removed in a future version."
|
||||
);
|
||||
}
|
||||
}
|
||||
#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,7 +162,7 @@ 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)
|
||||
{
|
||||
@@ -200,7 +199,7 @@ public abstract class ExportCommandBase : DiscordCommandBase
|
||||
try
|
||||
{
|
||||
await ctx.StartTaskAsync(
|
||||
channel.GetHierarchicalName(),
|
||||
Markup.Escape(channel.GetHierarchicalName()),
|
||||
async progress =>
|
||||
{
|
||||
var guild = await Discord.GetGuildAsync(
|
||||
@@ -244,9 +243,11 @@ public abstract class ExportCommandBase : DiscordCommandBase
|
||||
// Print the result
|
||||
using (console.WithForegroundColor(ConsoleColor.White))
|
||||
{
|
||||
await console.Output.WriteLineAsync(
|
||||
$"Successfully exported {channels.Count - errorsByChannel.Count} channel(s)."
|
||||
);
|
||||
await console
|
||||
.Output
|
||||
.WriteLineAsync(
|
||||
$"Successfully exported {channels.Count - errorsByChannel.Count} channel(s)."
|
||||
);
|
||||
}
|
||||
|
||||
// Print errors
|
||||
@@ -256,9 +257,11 @@ public abstract class ExportCommandBase : DiscordCommandBase
|
||||
|
||||
using (console.WithForegroundColor(ConsoleColor.Red))
|
||||
{
|
||||
await console.Error.WriteLineAsync(
|
||||
$"Failed to export {errorsByChannel.Count} the following channel(s):"
|
||||
);
|
||||
await console
|
||||
.Error
|
||||
.WriteLineAsync(
|
||||
$"Failed to export {errorsByChannel.Count} the following channel(s):"
|
||||
);
|
||||
}
|
||||
|
||||
foreach (var (channel, error) in errorsByChannel)
|
||||
@@ -320,33 +323,51 @@ public abstract class ExportCommandBase : DiscordCommandBase
|
||||
// Support Ukraine callout
|
||||
if (!IsUkraineSupportMessageDisabled)
|
||||
{
|
||||
console.Output.WriteLine(
|
||||
"┌────────────────────────────────────────────────────────────────────┐"
|
||||
);
|
||||
console.Output.WriteLine(
|
||||
"│ Thank you for supporting Ukraine <3 │"
|
||||
);
|
||||
console.Output.WriteLine(
|
||||
"│ │"
|
||||
);
|
||||
console.Output.WriteLine(
|
||||
"│ As Russia wages a genocidal war against my country, │"
|
||||
);
|
||||
console.Output.WriteLine(
|
||||
"│ I'm grateful to everyone who continues to │"
|
||||
);
|
||||
console.Output.WriteLine(
|
||||
"│ stand with Ukraine in our fight for freedom. │"
|
||||
);
|
||||
console.Output.WriteLine(
|
||||
"│ │"
|
||||
);
|
||||
console.Output.WriteLine(
|
||||
"│ Learn more: https://tyrrrz.me/ukraine │"
|
||||
);
|
||||
console.Output.WriteLine(
|
||||
"└────────────────────────────────────────────────────────────────────┘"
|
||||
);
|
||||
console
|
||||
.Output
|
||||
.WriteLine(
|
||||
"┌────────────────────────────────────────────────────────────────────┐"
|
||||
);
|
||||
console
|
||||
.Output
|
||||
.WriteLine(
|
||||
"│ Thank you for supporting Ukraine <3 │"
|
||||
);
|
||||
console
|
||||
.Output
|
||||
.WriteLine(
|
||||
"│ │"
|
||||
);
|
||||
console
|
||||
.Output
|
||||
.WriteLine(
|
||||
"│ As Russia wages a genocidal war against my country, │"
|
||||
);
|
||||
console
|
||||
.Output
|
||||
.WriteLine(
|
||||
"│ I'm grateful to everyone who continues to │"
|
||||
);
|
||||
console
|
||||
.Output
|
||||
.WriteLine(
|
||||
"│ stand with Ukraine in our fight for freedom. │"
|
||||
);
|
||||
console
|
||||
.Output
|
||||
.WriteLine(
|
||||
"│ │"
|
||||
);
|
||||
console
|
||||
.Output
|
||||
.WriteLine(
|
||||
"│ Learn more: https://tyrrrz.me/ukraine │"
|
||||
);
|
||||
console
|
||||
.Output
|
||||
.WriteLine(
|
||||
"└────────────────────────────────────────────────────────────────────┘"
|
||||
);
|
||||
console.Output.WriteLine("");
|
||||
}
|
||||
|
||||
|
||||
@@ -54,9 +54,9 @@ public class ExportAllCommand : ExportCommandBase
|
||||
await foreach (var guild in Discord.GetUserGuildsAsync(cancellationToken))
|
||||
{
|
||||
// Regular channels
|
||||
await console.Output.WriteLineAsync(
|
||||
$"Fetching channels for guild '{guild.Name}'..."
|
||||
);
|
||||
await console
|
||||
.Output
|
||||
.WriteLineAsync($"Fetching channels for guild '{guild.Name}'...");
|
||||
|
||||
var fetchedChannelsCount = 0;
|
||||
await console
|
||||
@@ -80,7 +80,10 @@ public class ExportAllCommand : ExportCommandBase
|
||||
|
||||
channels.Add(channel);
|
||||
|
||||
ctx.Status($"Fetched '{channel.GetHierarchicalName()}'.");
|
||||
ctx.Status(
|
||||
Markup.Escape($"Fetched '{channel.GetHierarchicalName()}'.")
|
||||
);
|
||||
|
||||
fetchedChannelsCount++;
|
||||
}
|
||||
}
|
||||
@@ -91,9 +94,9 @@ public class ExportAllCommand : ExportCommandBase
|
||||
// Threads
|
||||
if (ThreadInclusionMode != ThreadInclusionMode.None)
|
||||
{
|
||||
await console.Output.WriteLineAsync(
|
||||
$"Fetching threads for guild '{guild.Name}'..."
|
||||
);
|
||||
await console
|
||||
.Output
|
||||
.WriteLineAsync($"Fetching threads for guild '{guild.Name}'...");
|
||||
|
||||
var fetchedThreadsCount = 0;
|
||||
await console
|
||||
@@ -114,15 +117,18 @@ public class ExportAllCommand : ExportCommandBase
|
||||
{
|
||||
channels.Add(thread);
|
||||
|
||||
ctx.Status($"Fetched '{thread.GetHierarchicalName()}'.");
|
||||
ctx.Status(
|
||||
Markup.Escape($"Fetched '{thread.GetHierarchicalName()}'.")
|
||||
);
|
||||
|
||||
fetchedThreadsCount++;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
await console.Output.WriteLineAsync(
|
||||
$"Fetched {fetchedThreadsCount} thread(s)."
|
||||
);
|
||||
await console
|
||||
.Output
|
||||
.WriteLineAsync($"Fetched {fetchedThreadsCount} thread(s).");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,7 +148,11 @@ public class ExportAllCommand : ExportCommandBase
|
||||
{
|
||||
foreach (var dumpChannel in dump.Channels)
|
||||
{
|
||||
ctx.Status($"Fetching '{dumpChannel.Name}' ({dumpChannel.Id})...");
|
||||
ctx.Status(
|
||||
Markup.Escape(
|
||||
$"Fetching '{dumpChannel.Name}' ({dumpChannel.Id})..."
|
||||
)
|
||||
);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -170,9 +180,9 @@ public class ExportAllCommand : ExportCommandBase
|
||||
|
||||
using (console.WithForegroundColor(ConsoleColor.Red))
|
||||
{
|
||||
await console.Error.WriteLineAsync(
|
||||
"Failed to access the following channel(s):"
|
||||
);
|
||||
await console
|
||||
.Error
|
||||
.WriteLineAsync("Failed to access the following channel(s):");
|
||||
}
|
||||
|
||||
foreach (var dumpChannel in inaccessibleChannels)
|
||||
|
||||
@@ -58,7 +58,8 @@ public class ExportGuildCommand : ExportCommandBase
|
||||
|
||||
channels.Add(channel);
|
||||
|
||||
ctx.Status($"Fetched '{channel.GetHierarchicalName()}'.");
|
||||
ctx.Status(Markup.Escape($"Fetched '{channel.GetHierarchicalName()}'."));
|
||||
|
||||
fetchedChannelsCount++;
|
||||
}
|
||||
}
|
||||
@@ -90,7 +91,8 @@ public class ExportGuildCommand : ExportCommandBase
|
||||
{
|
||||
channels.Add(thread);
|
||||
|
||||
ctx.Status($"Fetched '{thread.GetHierarchicalName()}'.");
|
||||
ctx.Status(Markup.Escape($"Fetched '{thread.GetHierarchicalName()}'."));
|
||||
|
||||
fetchedThreadsCount++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,9 +64,9 @@ public class GetChannelsCommand : DiscordCommandBase
|
||||
foreach (var channel in channels)
|
||||
{
|
||||
// Channel ID
|
||||
await console.Output.WriteAsync(
|
||||
channel.Id.ToString().PadRight(channelIdMaxLength, ' ')
|
||||
);
|
||||
await console
|
||||
.Output
|
||||
.WriteAsync(channel.Id.ToString().PadRight(channelIdMaxLength, ' '));
|
||||
|
||||
// Separator
|
||||
using (console.WithForegroundColor(ConsoleColor.DarkGray))
|
||||
@@ -88,9 +88,11 @@ public class GetChannelsCommand : DiscordCommandBase
|
||||
await console.Output.WriteAsync(" * ");
|
||||
|
||||
// Thread ID
|
||||
await console.Output.WriteAsync(
|
||||
channelThread.Id.ToString().PadRight(channelThreadIdMaxLength, ' ')
|
||||
);
|
||||
await console
|
||||
.Output
|
||||
.WriteAsync(
|
||||
channelThread.Id.ToString().PadRight(channelThreadIdMaxLength, ' ')
|
||||
);
|
||||
|
||||
// Separator
|
||||
using (console.WithForegroundColor(ConsoleColor.DarkGray))
|
||||
@@ -106,9 +108,9 @@ public class GetChannelsCommand : DiscordCommandBase
|
||||
|
||||
// Thread status
|
||||
using (console.WithForegroundColor(ConsoleColor.White))
|
||||
await console.Output.WriteLineAsync(
|
||||
channelThread.IsArchived ? "Archived" : "Active"
|
||||
);
|
||||
await console
|
||||
.Output
|
||||
.WriteLineAsync(channelThread.IsArchived ? "Archived" : "Active");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,9 +33,9 @@ public class GetDirectChannelsCommand : DiscordCommandBase
|
||||
foreach (var channel in channels)
|
||||
{
|
||||
// Channel ID
|
||||
await console.Output.WriteAsync(
|
||||
channel.Id.ToString().PadRight(channelIdMaxLength, ' ')
|
||||
);
|
||||
await console
|
||||
.Output
|
||||
.WriteAsync(channel.Id.ToString().PadRight(channelIdMaxLength, ' '));
|
||||
|
||||
// Separator
|
||||
using (console.WithForegroundColor(ConsoleColor.DarkGray))
|
||||
|
||||
@@ -15,18 +15,20 @@ public class GuideCommand : ICommand
|
||||
using (console.WithForegroundColor(ConsoleColor.White))
|
||||
console.Output.WriteLine("To get user token:");
|
||||
|
||||
console.Output.WriteLine(
|
||||
" * Automating user accounts is technically against TOS — USE AT YOUR OWN RISK!"
|
||||
);
|
||||
console
|
||||
.Output
|
||||
.WriteLine(
|
||||
" * Automating user accounts is technically against TOS — USE AT YOUR OWN RISK!"
|
||||
);
|
||||
console.Output.WriteLine(" 1. Open Discord in your web browser and login");
|
||||
console.Output.WriteLine(" 2. Open any server or direct message channel");
|
||||
console.Output.WriteLine(" 3. Press Ctrl+Shift+I to show developer tools");
|
||||
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 containing \"messages?limit=50\" or similar");
|
||||
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");
|
||||
@@ -40,9 +42,11 @@ public class GuideCommand : ICommand
|
||||
console.Output.WriteLine(" 2. Open your application's settings");
|
||||
console.Output.WriteLine(" 3. Navigate to the Bot section on the left");
|
||||
console.Output.WriteLine(" 4. Under Token click Copy");
|
||||
console.Output.WriteLine(
|
||||
" * Your bot needs to have Message Content Intent enabled to read messages"
|
||||
);
|
||||
console
|
||||
.Output
|
||||
.WriteLine(
|
||||
" * Your bot needs to have Message Content Intent enabled to read messages"
|
||||
);
|
||||
console.Output.WriteLine();
|
||||
|
||||
// Guild or channel ID
|
||||
@@ -53,20 +57,22 @@ public class GuideCommand : ICommand
|
||||
console.Output.WriteLine(" 2. Open Settings");
|
||||
console.Output.WriteLine(" 3. Go to Advanced section");
|
||||
console.Output.WriteLine(" 4. Enable Developer Mode");
|
||||
console.Output.WriteLine(
|
||||
" 5. Right-click on the desired guild or channel and click Copy Server ID or Copy Channel ID"
|
||||
);
|
||||
console
|
||||
.Output
|
||||
.WriteLine(
|
||||
" 5. Right-click on the desired guild or channel and click Copy Server ID or Copy Channel ID"
|
||||
);
|
||||
console.Output.WriteLine();
|
||||
|
||||
// Docs link
|
||||
using (console.WithForegroundColor(ConsoleColor.White))
|
||||
console.Output.WriteLine(
|
||||
"If you have questions or issues, please refer to the documentation:"
|
||||
);
|
||||
console
|
||||
.Output
|
||||
.WriteLine("If you have questions or issues, please refer to the documentation:");
|
||||
using (console.WithForegroundColor(ConsoleColor.DarkCyan))
|
||||
console.Output.WriteLine(
|
||||
"https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs"
|
||||
);
|
||||
console
|
||||
.Output
|
||||
.WriteLine("https://github.com/Tyrrrz/DiscordChatExporter/blob/master/.docs");
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CliFx" Version="2.3.4" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.25.0" PrivateAssets="all" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" 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" />
|
||||
|
||||
@@ -44,8 +44,7 @@ internal static class ConsoleExtensions
|
||||
var actualDescription = !string.IsNullOrWhiteSpace(description) ? description : "...";
|
||||
|
||||
var progressTask = context.AddTask(
|
||||
// Don't recognize random square brackets as style tags
|
||||
Markup.Escape(actualDescription),
|
||||
actualDescription,
|
||||
new ProgressTaskSettings { MaxValue = 1 }
|
||||
);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using JsonExtensions.Reading;
|
||||
using System.Text.Json;
|
||||
using JsonExtensions.Reading;
|
||||
|
||||
namespace DiscordChatExporter.Core.Discord.Data.Embeds;
|
||||
|
||||
|
||||
@@ -12,9 +12,11 @@ public partial record SpotifyTrackEmbedProjection
|
||||
private static string? TryParseTrackId(string embedUrl)
|
||||
{
|
||||
// https://open.spotify.com/track/1LHZMWefF9502NPfArRfvP?si=3efac6ce9be04f0a
|
||||
var trackId = Regex.Match(embedUrl, @"spotify\.com/track/(.*?)(?:\?|&|/|$)").Groups[
|
||||
1
|
||||
].Value;
|
||||
var trackId = Regex
|
||||
.Match(embedUrl, @"spotify\.com/track/(.*?)(?:\?|&|/|$)")
|
||||
.Groups[1]
|
||||
.Value;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(trackId))
|
||||
return trackId;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ public record Interaction(Snowflake Id, string Name, User User)
|
||||
public static Interaction Parse(JsonElement json)
|
||||
{
|
||||
var id = json.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse);
|
||||
var name = json.GetProperty("name").GetNonWhiteSpaceString();
|
||||
var name = json.GetProperty("name").GetNonNullString(); // may be empty, but not null
|
||||
var user = json.GetProperty("user").Pipe(User.Parse);
|
||||
|
||||
return new Interaction(id, name, user);
|
||||
|
||||
@@ -99,7 +99,8 @@ public partial record Message
|
||||
if (trailingEmbeds.Any())
|
||||
{
|
||||
// Concatenate all images into one embed
|
||||
var images = embed.Images
|
||||
var images = embed
|
||||
.Images
|
||||
.Concat(trailingEmbeds.SelectMany(e => e.Images))
|
||||
.ToArray();
|
||||
|
||||
|
||||
@@ -40,10 +40,12 @@ public class DiscordClient
|
||||
|
||||
// Don't validate because the token can have special characters
|
||||
// https://github.com/Tyrrrz/DiscordChatExporter/issues/828
|
||||
request.Headers.TryAddWithoutValidation(
|
||||
"Authorization",
|
||||
tokenKind == TokenKind.Bot ? $"Bot {_token}" : _token
|
||||
);
|
||||
request
|
||||
.Headers
|
||||
.TryAddWithoutValidation(
|
||||
"Authorization",
|
||||
tokenKind == TokenKind.Bot ? $"Bot {_token}" : _token
|
||||
);
|
||||
|
||||
var response = await Http.Client.SendAsync(
|
||||
request,
|
||||
@@ -58,11 +60,13 @@ public class DiscordClient
|
||||
// require properly keeping track of Discord's global/per-route/per-resource
|
||||
// rate limits and that's just way too much effort.
|
||||
// https://discord.com/developers/docs/topics/rate-limits
|
||||
var remainingRequestCount = response.Headers
|
||||
var remainingRequestCount = response
|
||||
.Headers
|
||||
.TryGetValue("X-RateLimit-Remaining")
|
||||
?.Pipe(s => int.Parse(s, CultureInfo.InvariantCulture));
|
||||
|
||||
var resetAfterDelay = response.Headers
|
||||
var resetAfterDelay = response
|
||||
.Headers
|
||||
.TryGetValue("X-RateLimit-Reset-After")
|
||||
?.Pipe(s => double.Parse(s, CultureInfo.InvariantCulture))
|
||||
.Pipe(TimeSpan.FromSeconds);
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AsyncKeyedLock" Version="6.2.1" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.25.0" PrivateAssets="all" />
|
||||
<PackageReference Include="AsyncKeyedLock" Version="6.2.2" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" PrivateAssets="all" />
|
||||
<PackageReference Include="Gress" Version="2.1.1" />
|
||||
<PackageReference Include="JsonExtensions" Version="1.2.0" />
|
||||
<PackageReference Include="Polly" Version="8.0.0" />
|
||||
<PackageReference Include="Polly" Version="8.1.0" />
|
||||
<PackageReference Include="RazorBlade" Version="0.4.4" />
|
||||
<PackageReference Include="Superpower" Version="3.0.0" />
|
||||
<PackageReference Include="WebMarkupMin.Core" Version="2.14.0" />
|
||||
<PackageReference Include="YoutubeExplode" Version="6.3.4" />
|
||||
<PackageReference Include="YoutubeExplode" Version="6.3.7" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -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,
|
||||
@@ -22,11 +20,18 @@ public class ChannelExporter
|
||||
{
|
||||
// Forum channels don't have messages, they are just a list of threads
|
||||
if (request.Channel.Kind == ChannelKind.GuildForum)
|
||||
throw new DiscordChatExporterException("Channel is a forum.");
|
||||
{
|
||||
throw new DiscordChatExporterException(
|
||||
"Channel is a forum and cannot be exported directly. "
|
||||
+ "You need to pull its threads and export them individually."
|
||||
);
|
||||
}
|
||||
|
||||
// Check if the channel is empty
|
||||
if (request.Channel.IsEmpty)
|
||||
{
|
||||
throw new DiscordChatExporterException("Channel does not contain any messages.");
|
||||
}
|
||||
|
||||
// Check if the 'after' boundary is valid
|
||||
if (request.After is not null && !request.Channel.MayHaveMessagesAfter(request.After.Value))
|
||||
|
||||
@@ -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,
|
||||
@@ -88,7 +83,7 @@ internal partial class CsvMessageWriter : MessageWriter
|
||||
await _writer.WriteAsync(',');
|
||||
|
||||
// Message timestamp
|
||||
await _writer.WriteAsync(CsvEncode(Context.FormatDate(message.Timestamp)));
|
||||
await _writer.WriteAsync(CsvEncode(Context.FormatDate(message.Timestamp, "o")));
|
||||
await _writer.WriteAsync(',');
|
||||
|
||||
// Message content
|
||||
|
||||
@@ -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
|
||||
@@ -65,7 +59,9 @@ internal partial class ExportAssetDownloader
|
||||
// Try to set the file date according to the last-modified header
|
||||
try
|
||||
{
|
||||
var lastModified = response.Content.Headers
|
||||
var lastModified = response
|
||||
.Content
|
||||
.Headers
|
||||
.TryGetValue("Last-Modified")
|
||||
?.Pipe(
|
||||
s =>
|
||||
|
||||
@@ -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();
|
||||
@@ -101,7 +92,8 @@ internal class ExportContext
|
||||
public Role? TryGetRole(Snowflake id) => _rolesById.GetValueOrDefault(id);
|
||||
|
||||
public IReadOnlyList<Role> GetUserRoles(Snowflake id) =>
|
||||
TryGetMember(id)?.RoleIds
|
||||
TryGetMember(id)
|
||||
?.RoleIds
|
||||
.Select(TryGetRole)
|
||||
.WhereNotNull()
|
||||
.OrderByDescending(r => r.Position)
|
||||
@@ -123,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
|
||||
@@ -133,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;
|
||||
|
||||
@@ -182,10 +182,9 @@ public partial class ExportRequest
|
||||
=> before?.ToDate().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)
|
||||
?? "",
|
||||
"%d"
|
||||
=> DateTimeOffset.Now.ToString(
|
||||
"yyyy-MM-dd",
|
||||
CultureInfo.InvariantCulture
|
||||
),
|
||||
=> DateTimeOffset
|
||||
.Now
|
||||
.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture),
|
||||
|
||||
"%%" => "%",
|
||||
_ => m.Value
|
||||
|
||||
@@ -26,12 +26,14 @@ internal class ContainsMessageFilter : MessageFilter
|
||||
|
||||
public override bool IsMatch(Message message) =>
|
||||
IsMatch(message.Content)
|
||||
|| message.Embeds.Any(
|
||||
e =>
|
||||
IsMatch(e.Title)
|
||||
|| IsMatch(e.Author?.Name)
|
||||
|| IsMatch(e.Description)
|
||||
|| IsMatch(e.Footer?.Text)
|
||||
|| e.Fields.Any(f => IsMatch(f.Name) || IsMatch(f.Value))
|
||||
);
|
||||
|| message
|
||||
.Embeds
|
||||
.Any(
|
||||
e =>
|
||||
IsMatch(e.Title)
|
||||
|| IsMatch(e.Author?.Name)
|
||||
|| IsMatch(e.Description)
|
||||
|| IsMatch(e.Footer?.Text)
|
||||
|| e.Fields.Any(f => IsMatch(f.Name) || IsMatch(f.Value))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,11 +11,13 @@ internal class MentionsMessageFilter : MessageFilter
|
||||
public MentionsMessageFilter(string value) => _value = value;
|
||||
|
||||
public override bool IsMatch(Message message) =>
|
||||
message.MentionedUsers.Any(
|
||||
user =>
|
||||
string.Equals(_value, user.Name, StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(_value, user.DisplayName, StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(_value, user.FullName, StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(_value, user.Id.ToString(), StringComparison.OrdinalIgnoreCase)
|
||||
);
|
||||
message
|
||||
.MentionedUsers
|
||||
.Any(
|
||||
user =>
|
||||
string.Equals(_value, user.Name, StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(_value, user.DisplayName, StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(_value, user.FullName, StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(_value, user.Id.ToString(), StringComparison.OrdinalIgnoreCase)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,10 +11,16 @@ internal class ReactionMessageFilter : MessageFilter
|
||||
public ReactionMessageFilter(string value) => _value = value;
|
||||
|
||||
public override bool IsMatch(Message message) =>
|
||||
message.Reactions.Any(
|
||||
r =>
|
||||
string.Equals(_value, r.Emoji.Id?.ToString(), StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(_value, r.Emoji.Name, StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(_value, r.Emoji.Code, StringComparison.OrdinalIgnoreCase)
|
||||
);
|
||||
message
|
||||
.Reactions
|
||||
.Any(
|
||||
r =>
|
||||
string.Equals(
|
||||
_value,
|
||||
r.Emoji.Id?.ToString(),
|
||||
StringComparison.OrdinalIgnoreCase
|
||||
)
|
||||
|| string.Equals(_value, r.Emoji.Name, StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(_value, r.Emoji.Code, StringComparison.OrdinalIgnoreCase)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -196,7 +193,8 @@ internal partial class HtmlMarkdownVisitor : MarkdownVisitor
|
||||
// Try to extract the message ID if the link points to a Discord message
|
||||
var linkedMessageId = Regex
|
||||
.Match(link.Url, @"^https?://(?:discord|discordapp)\.com/channels/.*?/(\d+)/?$")
|
||||
.Groups[1].Value;
|
||||
.Groups[1]
|
||||
.Value;
|
||||
|
||||
_buffer.Append(
|
||||
!string.IsNullOrWhiteSpace(linkedMessageId)
|
||||
|
||||
@@ -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,
|
||||
@@ -143,6 +138,31 @@ internal class JsonMessageWriter : MessageWriter
|
||||
await _writer.FlushAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async ValueTask WriteEmbedVideoAsync(
|
||||
EmbedVideo embedVideo,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
_writer.WriteStartObject();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(embedVideo.Url))
|
||||
{
|
||||
_writer.WriteString(
|
||||
"url",
|
||||
await Context.ResolveAssetUrlAsync(
|
||||
embedVideo.ProxyUrl ?? embedVideo.Url,
|
||||
cancellationToken
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
_writer.WriteNumber("width", embedVideo.Width);
|
||||
_writer.WriteNumber("height", embedVideo.Height);
|
||||
|
||||
_writer.WriteEndObject();
|
||||
await _writer.FlushAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async ValueTask WriteEmbedFooterAsync(
|
||||
EmbedFooter embedFooter,
|
||||
CancellationToken cancellationToken = default
|
||||
@@ -224,6 +244,12 @@ internal class JsonMessageWriter : MessageWriter
|
||||
await WriteEmbedImageAsync(embed.Image, cancellationToken);
|
||||
}
|
||||
|
||||
if (embed.Video is not null)
|
||||
{
|
||||
_writer.WritePropertyName("video");
|
||||
await WriteEmbedVideoAsync(embed.Video, cancellationToken);
|
||||
}
|
||||
|
||||
if (embed.Footer is not null)
|
||||
{
|
||||
_writer.WritePropertyName("footer");
|
||||
@@ -419,12 +445,14 @@ internal class JsonMessageWriter : MessageWriter
|
||||
|
||||
_writer.WriteStartArray("users");
|
||||
await foreach (
|
||||
var user in Context.Discord.GetMessageReactionsAsync(
|
||||
Context.Request.Channel.Id,
|
||||
message.Id,
|
||||
reaction.Emoji,
|
||||
cancellationToken
|
||||
)
|
||||
var user in Context
|
||||
.Discord
|
||||
.GetMessageReactionsAsync(
|
||||
Context.Request.Channel.Id,
|
||||
message.Id,
|
||||
reaction.Emoji,
|
||||
cancellationToken
|
||||
)
|
||||
)
|
||||
{
|
||||
_writer.WriteStartObject();
|
||||
|
||||
@@ -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)
|
||||
@@ -44,10 +39,10 @@ internal partial class MessageExporter : IAsyncDisposable
|
||||
// Ensure that the partition limit has not been reached
|
||||
if (
|
||||
_writer is not null
|
||||
&& _context.Request.PartitionLimit.IsReached(
|
||||
_writer.MessagesWritten,
|
||||
_writer.BytesWritten
|
||||
)
|
||||
&& _context
|
||||
.Request
|
||||
.PartitionLimit
|
||||
.IsReached(_writer.MessagesWritten, _writer.BytesWritten)
|
||||
)
|
||||
{
|
||||
await ResetWriterAsync(cancellationToken);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -30,7 +30,8 @@ internal class AggregateMatcher<T> : IMatcher<T>
|
||||
|
||||
// If this match is earlier than previous earliest - replace
|
||||
if (
|
||||
earliestMatch is null || match.Segment.StartIndex < earliestMatch.Segment.StartIndex
|
||||
earliestMatch is null
|
||||
|| match.Segment.StartIndex < earliestMatch.Segment.StartIndex
|
||||
)
|
||||
earliestMatch = match;
|
||||
|
||||
|
||||
@@ -24,12 +24,10 @@ internal class StringMatcher<T> : IMatcher<T>
|
||||
|
||||
public ParsedMatch<T>? TryMatch(StringSegment segment)
|
||||
{
|
||||
var index = segment.Source.IndexOf(
|
||||
_needle,
|
||||
segment.StartIndex,
|
||||
segment.Length,
|
||||
_comparison
|
||||
);
|
||||
var index = segment
|
||||
.Source
|
||||
.IndexOf(_needle, segment.StartIndex, segment.Length, _comparison);
|
||||
|
||||
if (index < 0)
|
||||
return null;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ using DiscordChatExporter.Gui.ViewModels;
|
||||
using DiscordChatExporter.Gui.ViewModels.Framework;
|
||||
using Stylet;
|
||||
using StyletIoC;
|
||||
|
||||
#if !DEBUG
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
|
||||
@@ -13,15 +13,14 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Cogwheel" Version="2.0.3" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.25.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Cogwheel" Version="2.0.4" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.26.1" 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.39" />
|
||||
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.77" />
|
||||
<PackageReference Include="Onova" Version="2.6.10" />
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Stylet" Version="1.3.6" />
|
||||
|
||||
@@ -66,7 +66,8 @@ public partial class SettingsService
|
||||
{
|
||||
try
|
||||
{
|
||||
return Registry.CurrentUser
|
||||
return Registry
|
||||
.CurrentUser
|
||||
.OpenSubKey(
|
||||
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
|
||||
false
|
||||
|
||||
@@ -12,8 +12,8 @@ using DiscordChatExporter.Gui.Models;
|
||||
using DiscordChatExporter.Gui.Services;
|
||||
using DiscordChatExporter.Gui.Utils;
|
||||
using DiscordChatExporter.Gui.ViewModels.Dialogs;
|
||||
using DiscordChatExporter.Gui.ViewModels.Messages;
|
||||
using DiscordChatExporter.Gui.ViewModels.Framework;
|
||||
using DiscordChatExporter.Gui.ViewModels.Messages;
|
||||
using Gress;
|
||||
using Gress.Completable;
|
||||
using Stylet;
|
||||
@@ -234,7 +234,8 @@ public class DashboardViewModel : PropertyChangedBase
|
||||
|
||||
var exporter = new ChannelExporter(_discord);
|
||||
|
||||
var channelProgressPairs = dialog.Channels!
|
||||
var channelProgressPairs = dialog
|
||||
.Channels!
|
||||
.Select(c => new { Channel = c, Progress = _progressMuxer.CreateInput() })
|
||||
.ToArray();
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -4,8 +4,8 @@ using DiscordChatExporter.Gui.Services;
|
||||
using DiscordChatExporter.Gui.Utils;
|
||||
using DiscordChatExporter.Gui.ViewModels.Components;
|
||||
using DiscordChatExporter.Gui.ViewModels.Dialogs;
|
||||
using DiscordChatExporter.Gui.ViewModels.Messages;
|
||||
using DiscordChatExporter.Gui.ViewModels.Framework;
|
||||
using DiscordChatExporter.Gui.ViewModels.Messages;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using Stylet;
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
**DiscordChatExporter** is an application that can be used to export message history from any [Discord](https://discord.com) channel to a file.
|
||||
It works with direct messages, group messages, and server channels, and supports Discord's dialect of markdown as well as most other rich media features.
|
||||
|
||||
> ❔ If you have questions or issues, **please refer to the [docs](.docs)**.
|
||||
<!-- Can't use a relative link here due to a bug in markdown parsing -->
|
||||
> ❔ If you have questions or issues, **please refer to the [docs](https://github.com/Tyrrrz/DiscordChatExporter/tree/master/.docs)**.
|
||||
|
||||
> 💬 If you want to chat, **join my [Discord server](https://discord.gg/2SUWKFnHSm)**.
|
||||
|
||||
@@ -57,7 +58,7 @@ The following table lists all available download options:
|
||||
<td>
|
||||
<ul>
|
||||
<li>🟢 <b><a href="https://github.com/Tyrrrz/DiscordChatExporter/releases/latest">Stable release</a></b> (<code>DiscordChatExporter.zip</code>)</li>
|
||||
<li>🟠 <a href="https://github.com/Tyrrrz/DiscordChatExporter/actions/workflows/main.yml">CI build</a> (<code>DiscordChatExporter.zip</code>)</li>
|
||||
<li>🟠 <a href="https://github.com/Tyrrrz/DiscordChatExporter/actions/workflows/main.yml">CI build</a> (<code>DiscordChatExporter.Gui.zip</code>)</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
@@ -70,8 +71,8 @@ The following table lists all available download options:
|
||||
<td><b>CLI</b></td>
|
||||
<td>
|
||||
<ul>
|
||||
<li>🟢 <b><a href="https://github.com/Tyrrrz/DiscordChatExporter/releases/latest">Stable release</a></b> (<code>DiscordChatExporter.CLI.zip</code></li>
|
||||
<li>🟠 <a href="https://github.com/Tyrrrz/DiscordChatExporter/actions/workflows/main.yml">CI build</a> (<code>DiscordChatExporter.CLI.zip</code>)</li>
|
||||
<li>🟢 <b><a href="https://github.com/Tyrrrz/DiscordChatExporter/releases/latest">Stable release</a></b> (<code>DiscordChatExporter.Cli.zip</code></li>
|
||||
<li>🟠 <a href="https://github.com/Tyrrrz/DiscordChatExporter/actions/workflows/main.yml">CI build</a> (<code>DiscordChatExporter.Cli.zip</code>)</li>
|
||||
<li>🐋 <a href="https://hub.docker.com/r/tyrrrz/discordchatexporter">Docker</a> (<code>tyrrrz/discordchatexporter</code>)</li>
|
||||
<li>📦 <a href="https://aur.archlinux.org/packages/discord-chat-exporter-cli">AUR</a> (<code>discord-chat-exporter-cli</code>)</li>
|
||||
<li>📦 <a href="https://search.nixos.org/packages?query=discordchatexporter-cli">Nix</a> (<code>discordchatexporter-cli</code>)</li>
|
||||
@@ -93,12 +94,12 @@ The following table lists all available download options:
|
||||
> 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.
|
||||
> 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.
|
||||
|
||||
Reference in New Issue
Block a user