mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-07-07 04:39:33 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
563f5cb67b | ||
|
|
1f20915b4d | ||
|
|
e58c7aefff |
@@ -1,3 +1,8 @@
|
||||
### v2.21.1 (19-Jul-2020)
|
||||
|
||||
- Fixed an issue where the export crashed if an embedded image has been deleted. Such media files are now ignored.
|
||||
- Changed the naming convention for downloaded media files so that the original file names are used when possible.
|
||||
|
||||
### v2.21 (18-Jul-2020)
|
||||
|
||||
- Added a new option that enables self-contained exports for all output formats. You can turn it on in the export setup dialog in GUI or using the `--media` option in CLI. When using this, the application will additionally download any media content directly referenced from the exported file instead of linking back to Discord CDN. The files which are downloaded include: guild icons, user avatars, attachments, embedded images, reaction emojis. Note that only files which are actually referenced by the export are downloaded, which means that, for example, user avatars will not be downloaded when using plain text export format. This option is not meant to enable complete offline viewing for HTML exports, but rather to make it easier to archive media content that may eventually get deleted from Discord servers. Also keep in mind that this option may make the export drastically slower and the total file size larger.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using DiscordChatExporter.Domain.Discord.Models;
|
||||
|
||||
@@ -60,10 +61,18 @@ namespace DiscordChatExporter.Domain.Exporting
|
||||
if (!Request.ShouldDownloadMedia)
|
||||
return url;
|
||||
|
||||
var filePath = await _mediaDownloader.DownloadAsync(url).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
var filePath = await _mediaDownloader.DownloadAsync(url).ConfigureAwait(false);
|
||||
|
||||
// Return relative path so that the output files can be copied around without breaking
|
||||
return Path.GetRelativePath(Request.OutputBaseDirPath, filePath);
|
||||
// Return relative path so that the output files can be copied around without breaking
|
||||
return Path.GetRelativePath(Request.OutputBaseDirPath, filePath);
|
||||
}
|
||||
catch (HttpRequestException)
|
||||
{
|
||||
// We don't want this to crash the exporting process in case of failure
|
||||
return url;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,39 +9,44 @@ using DiscordChatExporter.Domain.Internal.Extensions;
|
||||
|
||||
namespace DiscordChatExporter.Domain.Exporting
|
||||
{
|
||||
internal partial class MediaDownloader
|
||||
internal class MediaDownloader
|
||||
{
|
||||
private readonly HttpClient _httpClient = Singleton.HttpClient;
|
||||
private readonly string _workingDirPath;
|
||||
|
||||
private readonly Dictionary<string, string> _mediaPathMap = new Dictionary<string, string>();
|
||||
private readonly Dictionary<string, string> _pathMap = new Dictionary<string, string>();
|
||||
|
||||
public MediaDownloader(string workingDirPath)
|
||||
{
|
||||
_workingDirPath = workingDirPath;
|
||||
}
|
||||
|
||||
private string GetRandomSuffix() => Guid.NewGuid().ToString().Replace("-", "").Substring(0, 8);
|
||||
|
||||
private string GetFileNameFromUrl(string url)
|
||||
{
|
||||
var originalFileName = Regex.Match(url, @".+/([^?]*)").Groups[1].Value;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(originalFileName))
|
||||
return GetRandomSuffix();
|
||||
|
||||
return $"{Path.GetFileNameWithoutExtension(originalFileName)}-{GetRandomSuffix()}{Path.GetExtension(originalFileName)}";
|
||||
}
|
||||
|
||||
// HACK: ConfigureAwait() is crucial here to enable sync-over-async in HtmlMessageWriter
|
||||
public async ValueTask<string> DownloadAsync(string url)
|
||||
{
|
||||
if (_mediaPathMap.TryGetValue(url, out var cachedFilePath))
|
||||
if (_pathMap.TryGetValue(url, out var cachedFilePath))
|
||||
return cachedFilePath;
|
||||
|
||||
var fileName = GetFileNameFromUrl(url);
|
||||
var filePath = Path.Combine(_workingDirPath, fileName);
|
||||
|
||||
Directory.CreateDirectory(_workingDirPath);
|
||||
|
||||
var extension = Path.GetExtension(GetFileNameFromUrl(url));
|
||||
var fileName = $"{Guid.NewGuid()}{extension}";
|
||||
var filePath = Path.Combine(_workingDirPath, fileName);
|
||||
|
||||
await _httpClient.DownloadAsync(url, filePath).ConfigureAwait(false);
|
||||
|
||||
return _mediaPathMap[url] = filePath;
|
||||
return _pathMap[url] = filePath;
|
||||
}
|
||||
}
|
||||
|
||||
internal partial class MediaDownloader
|
||||
{
|
||||
private static string GetFileNameFromUrl(string url) =>
|
||||
Regex.Match(url, @".+/([^?]*)").Groups[1].Value;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<Version>2.21</Version>
|
||||
<Version>2.21.1</Version>
|
||||
<Company>Tyrrrz</Company>
|
||||
<Copyright>Copyright (c) Alexey Golub</Copyright>
|
||||
<LangVersion>latest</LangVersion>
|
||||
|
||||
Reference in New Issue
Block a user