Compare commits

...

4 Commits

Author SHA1 Message Date
Tyrrrz a405ab184e Update version 2022-09-08 16:57:00 +03:00
Tyrrrz b861a69799 Recognize existing directories as valid output paths in CLI
Closes #917
2022-09-04 18:14:22 +03:00
Tyrrrz d53b4c825a Update usage guide 2022-09-02 13:29:56 +03:00
Oleksii Holub 30678e96e5 Move into maintenance mode 2022-08-26 18:01:19 +03:00
8 changed files with 56 additions and 79 deletions
+3
View File
@@ -1,5 +1,8 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: ⚠ Feature request
url: https://github.com/Tyrrrz/.github/blob/master/docs/project-status.md
about: Sorry, but this project is in maintenance mode and no longer accepts new feature requests.
- name: 💬 Discord server - name: 💬 Discord server
url: https://discord.gg/2SUWKFnHSm url: https://discord.gg/2SUWKFnHSm
about: Chat with the project community. about: Chat with the project community.
@@ -1,42 +0,0 @@
name: ✨ Feature request
description: Request a new feature.
labels: [enhancement]
body:
- type: markdown
attributes:
value: |
🧐 **Guidelines:**
- Search through [existing issues](https://github.com/Tyrrrz/DiscordChatExporter/issues?q=is%3Aissue) first to ensure that this feature has not been requested before.
- Write a descriptive title for your issue. Avoid generic or vague titles such as "Some suggestions" or "Ideas for improvement".
- Keep your issue focused on one single problem. If you have multiple feature requests, please create separate issues for each of them.
- Provide as much context as possible in the details section. Include screenshots, screen recordings, links, references, or anything else you may consider relevant.
- If you want to ask a question instead of requesting a feature, please use [discussions](https://github.com/Tyrrrz/DiscordChatExporter/discussions/new) instead.
- type: dropdown
attributes:
label: Flavor
description: Is this feature request related to specific flavor(s) of DiscordChatExporter? If not applicable, leave this field blank.
multiple: true
options:
- GUI (Graphical User Interface)
- CLI (Command Line Interface)
- type: dropdown
attributes:
label: Export format
description: Is this feature request related to specific export format(s)? If not applicable, leave this field blank.
multiple: true
options:
- HTML
- TXT
- JSON
- CSV
- type: textarea
attributes:
label: Details
description: Clear and thorough explanation of the feature you have in mind.
validations:
required: true
+5
View File
@@ -1,3 +1,8 @@
### v2.35.2 (08-Sep-2022)
- Updated usage guide to mention the need to enable "Message Content Intent" to use a bot as a medium for exporting messages.
- [CLI] Fixed an issue where passing an existing directory as the output path failed when exporting multiple channels (for example, when running `exportdm`). An ambiguous output path will now always be treated as a directory path if that directory already exists. If it doesn't exist, it will be treated as a file path, matching the previous behavior.
### v2.35.1 (26-Aug-2022) ### v2.35.1 (26-Aug-2022)
- Added `~` character as an alias for `-` when negating a message filter. This should make it easier to use negated filters from CLI where the dash character already has other meanings. - Added `~` character as an alias for `-` when negating a message filter. This should make it easier to use negated filters from CLI where the dash character already has other meanings.
+1 -1
View File
@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<Version>2.35.1</Version> <Version>2.35.2</Version>
<Company>Tyrrrz</Company> <Company>Tyrrrz</Company>
<Copyright>Copyright (c) Oleksii Holub</Copyright> <Copyright>Copyright (c) Oleksii Holub</Copyright>
<LangVersion>preview</LangVersion> <LangVersion>preview</LangVersion>
@@ -26,7 +26,7 @@ public abstract class ExportCommandBase : TokenCommandBase
[CommandOption( [CommandOption(
"output", "output",
'o', 'o',
Description = "Output file or directory path." Description = "Output file or directory path. Directory path should end in a slash."
)] )]
public string OutputPath public string OutputPath
{ {
@@ -97,8 +97,7 @@ public abstract class ExportCommandBase : TokenCommandBase
protected async ValueTask ExecuteAsync(IConsole console, IReadOnlyList<Channel> channels) protected async ValueTask ExecuteAsync(IConsole console, IReadOnlyList<Channel> channels)
{ {
var cancellationToken = console.RegisterCancellationHandler(); // Reuse media option should only be used when the media option is set.
// https://github.com/Tyrrrz/DiscordChatExporter/issues/425 // https://github.com/Tyrrrz/DiscordChatExporter/issues/425
if (ShouldReuseMedia && !ShouldDownloadMedia) if (ShouldReuseMedia && !ShouldDownloadMedia)
{ {
@@ -107,14 +106,26 @@ public abstract class ExportCommandBase : TokenCommandBase
); );
} }
// Make sure the user does not try to export all channels into a single file.
// Output path must either be a directory, or contain template tokens.
// https://github.com/Tyrrrz/DiscordChatExporter/issues/799 // https://github.com/Tyrrrz/DiscordChatExporter/issues/799
if (channels.Count > 1 && !PathEx.IsDirectoryPath(OutputPath) && !OutputPath.Contains('%')) // https://github.com/Tyrrrz/DiscordChatExporter/issues/917
var isValidOutputPath =
// Anything is valid when exporting a single channel
channels.Count <= 1 ||
// When using template tokens, assume the user knows what they're doing
OutputPath.Contains('%') ||
// Otherwise, require an existing directory or an unambiguous directory path
Directory.Exists(OutputPath) || PathEx.IsDirectoryPath(OutputPath);
if (!isValidOutputPath)
{ {
throw new CommandException( throw new CommandException(
"Attempted to export multiple channels, but the output path is neither a directory nor a template." "Attempted to export multiple channels, but the output path is neither a directory nor a template."
); );
} }
var cancellationToken = console.RegisterCancellationHandler();
var errors = new ConcurrentDictionary<Channel, string>(); var errors = new ConcurrentDictionary<Channel, string>();
// Export // Export
@@ -17,13 +17,14 @@ public class GuideCommand : ICommand
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(" 1. Open Discord in your web browser and login");
console.Output.WriteLine(" 2. Press Ctrl+Shift+I to show developer tools"); console.Output.WriteLine(" 2. Open any server or direct message channel");
console.Output.WriteLine(" 3. Navigate to the Network tab"); console.Output.WriteLine(" 3. Press Ctrl+Shift+I to show developer tools");
console.Output.WriteLine(" 4. Press Ctrl+R to reload"); console.Output.WriteLine(" 4. Navigate to the Network tab");
console.Output.WriteLine(" 5. Search for a request containing \"messages?limit=50\" or similar"); console.Output.WriteLine(" 5. Press Ctrl+R to reload");
console.Output.WriteLine(" 6. Select the Headers tab on the right"); console.Output.WriteLine(" 6. Search for a request containing \"messages?limit=50\" or similar");
console.Output.WriteLine(" 7. Scroll down to the Request Headers section"); console.Output.WriteLine(" 7. Select the Headers tab on the right");
console.Output.WriteLine(" 8. Copy the value of the \"authorization\" header"); console.Output.WriteLine(" 8. Scroll down to the Request Headers section");
console.Output.WriteLine(" 9. Copy the value of the \"authorization\" header");
console.Output.WriteLine(); console.Output.WriteLine();
// Bot token // Bot token
@@ -34,6 +35,7 @@ public class GuideCommand : ICommand
console.Output.WriteLine(" 2. Open your application's settings"); console.Output.WriteLine(" 2. Open your application's settings");
console.Output.WriteLine(" 3. Navigate to the Bot section on the left"); console.Output.WriteLine(" 3. Navigate to the Bot section on the left");
console.Output.WriteLine(" 4. Under Token click Copy"); 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(); console.Output.WriteLine();
// Guild or channel ID // Guild or channel ID
@@ -135,22 +135,14 @@
Grid.Row="2" Grid.Row="2"
Background="{DynamicResource MaterialDesignCardBackground}" Background="{DynamicResource MaterialDesignCardBackground}"
IsEnabled="{Binding IsBusy, Converter={x:Static converters:InverseBoolConverter.Instance}}"> IsEnabled="{Binding IsBusy, Converter={x:Static converters:InverseBoolConverter.Instance}}">
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontWeight" Value="Light" />
</Style>
</Grid.Resources>
<!-- Placeholder / usage instructions --> <!-- Placeholder / usage instructions -->
<Grid Visibility="{Binding AvailableGuilds, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}}"> <Grid Visibility="{Binding AvailableGuilds, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}}">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> <ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<TextBlock <TextBlock
Margin="32,16" Margin="32,16"
FontSize="14" FontSize="14"
FontWeight="Light"
LineHeight="20"> LineHeight="20">
<Run FontSize="18" Text="Please provide authentication token to continue" />
<LineBreak />
<LineBreak />
<!-- User token --> <!-- User token -->
<InlineUIContainer> <InlineUIContainer>
<materialDesign:PackIcon <materialDesign:PackIcon
@@ -158,7 +150,7 @@
Foreground="{DynamicResource PrimaryHueMidBrush}" Foreground="{DynamicResource PrimaryHueMidBrush}"
Kind="Account" /> Kind="Account" />
</InlineUIContainer> </InlineUIContainer>
<Run FontSize="16" Text="To get token for your personal account:" /> <Run FontSize="16" FontWeight="SemiBold" Text="To get token for your personal account:" />
<LineBreak /> <LineBreak />
<Run Text="* Automating user accounts is technically against TOS —" /> <Run Text="* Automating user accounts is technically against TOS —" />
<Run FontWeight="SemiBold" Text="use at your own risk" /><Run Text="!" /> <Run FontWeight="SemiBold" Text="use at your own risk" /><Run Text="!" />
@@ -169,31 +161,33 @@
</Hyperlink> </Hyperlink>
<Run Text="and login" /> <Run Text="and login" />
<LineBreak /> <LineBreak />
<Run Text="2. Press" /> <Run Text="2. Open any server or direct message channel" />
<LineBreak />
<Run Text="3. Press" />
<Run FontWeight="SemiBold" Text="Ctrl+Shift+I" /> <Run FontWeight="SemiBold" Text="Ctrl+Shift+I" />
<Run Text="to show developer tools" /> <Run Text="to show developer tools" />
<LineBreak /> <LineBreak />
<Run Text="3. Navigate to the" /> <Run Text="4. Navigate to the" />
<Run FontWeight="SemiBold" Text="Network" /> <Run FontWeight="SemiBold" Text="Network" />
<Run Text="tab" /> <Run Text="tab" />
<LineBreak /> <LineBreak />
<Run Text="4. Press" /> <Run Text="5. Press" />
<Run FontWeight="SemiBold" Text="Ctrl+R" /> <Run FontWeight="SemiBold" Text="Ctrl+R" />
<Run Text="to reload" /> <Run Text="to reload" />
<LineBreak /> <LineBreak />
<Run Text="5. Search for a request containing" /> <Run Text="6. Search for a request containing" />
<Run FontWeight="SemiBold" Text="messages?limit=50" /> <Run FontWeight="SemiBold" Text="messages?limit=50" />
<Run Text="or similar" /> <Run Text="or similar" />
<LineBreak /> <LineBreak />
<Run Text="6. Select the" /> <Run Text="7. Select the" />
<Run FontWeight="SemiBold" Text="Headers" /> <Run FontWeight="SemiBold" Text="Headers" />
<Run Text=" tab on the right" /> <Run Text=" tab on the right" />
<LineBreak /> <LineBreak />
<Run Text="7. Scroll down to the" /> <Run Text="8. Scroll down to the" />
<Run FontWeight="SemiBold" Text="Request Headers" /> <Run FontWeight="SemiBold" Text="Request Headers" />
<Run Text="section" /> <Run Text="section" />
<LineBreak /> <LineBreak />
<Run Text="8. Copy the value of the" /> <Run Text="9. Copy the value of the" />
<Run FontWeight="SemiBold" Text="authorization" /> <Run FontWeight="SemiBold" Text="authorization" />
<Run Text="header" /> <Run Text="header" />
<LineBreak /> <LineBreak />
@@ -206,7 +200,7 @@
Foreground="{DynamicResource PrimaryHueMidBrush}" Foreground="{DynamicResource PrimaryHueMidBrush}"
Kind="Robot" /> Kind="Robot" />
</InlineUIContainer> </InlineUIContainer>
<Run FontSize="16" Text="To get token for a bot account:" /> <Run FontSize="16" FontWeight="SemiBold" Text="To get token for a bot account:" />
<LineBreak /> <LineBreak />
<Run Text="1. Open Discord" /> <Run Text="1. Open Discord" />
<Hyperlink Command="{s:Action OpenDiscordDeveloperPortal}"> <Hyperlink Command="{s:Action OpenDiscordDeveloperPortal}">
@@ -224,10 +218,14 @@
<Run Text="click" /> <Run Text="click" />
<Run FontWeight="SemiBold" Text="Copy" /> <Run FontWeight="SemiBold" Text="Copy" />
<LineBreak /> <LineBreak />
<Run Text="* Your bot needs to have" />
<Run FontWeight="SemiBold" Text="Message Content Intent" />
<Run Text="enabled to read messages" />
<LineBreak />
<LineBreak /> <LineBreak />
<Run FontSize="16" Text="If you have questions or issues, please refer to the" /> <Run Text="If you have questions or issues, please refer to the" />
<Hyperlink Command="{s:Action ShowHelp}" FontSize="16">wiki</Hyperlink><Run FontSize="16" Text="." /> <Hyperlink Command="{s:Action ShowHelp}">wiki</Hyperlink><Run Text="." />
</TextBlock> </TextBlock>
</ScrollViewer> </ScrollViewer>
</Grid> </Grid>
+1 -1
View File
@@ -9,7 +9,7 @@
[![Donate](https://img.shields.io/badge/donate-$$$-8a2be2.svg)](https://tyrrrz.me/donate) [![Donate](https://img.shields.io/badge/donate-$$$-8a2be2.svg)](https://tyrrrz.me/donate)
[![Fuck Russia](https://img.shields.io/badge/fuck-russia-e4181c.svg?labelColor=000000)](https://twitter.com/tyrrrz/status/1495972128977571848) [![Fuck Russia](https://img.shields.io/badge/fuck-russia-e4181c.svg?labelColor=000000)](https://twitter.com/tyrrrz/status/1495972128977571848)
> 🟢 **Project status**: active<sup>[[?]](https://github.com/Tyrrrz/.github/blob/master/docs/project-status.md)</sup> > 🟡 **Project status**: maintenance mode<sup>[[?]](https://github.com/Tyrrrz/.github/blob/master/docs/project-status.md)</sup>
**DiscordChatExporter** can be used to export message history from a [Discord](https://discord.com) channel to a file. **DiscordChatExporter** can be used to export message history from a [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 all other rich media features. It works with direct messages, group messages, and server channels, and supports Discord's dialect of markdown as well as all other rich media features.