mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2025-06-05 01:03:44 -04:00
Clean up
This commit is contained in:
parent
768fb88c8c
commit
c69211797f
3 changed files with 65 additions and 77 deletions
|
@ -48,23 +48,22 @@ public static class ExportWrapper
|
||||||
var fileName = channelId.ToString() + '.' + format.GetFileExtension();
|
var fileName = channelId.ToString() + '.' + format.GetFileExtension();
|
||||||
var filePath = Path.Combine(DirPath, fileName);
|
var filePath = Path.Combine(DirPath, fileName);
|
||||||
|
|
||||||
// Lock separately for each channel and format
|
using var _ = await Locker.LockAsync(filePath);
|
||||||
using (await Locker.LockAsync(filePath))
|
using var console = new FakeConsole();
|
||||||
{
|
|
||||||
// Perform the export only if it hasn't been done before
|
|
||||||
if (!File.Exists(filePath))
|
|
||||||
{
|
|
||||||
await new ExportChannelsCommand
|
|
||||||
{
|
|
||||||
Token = Secrets.DiscordToken,
|
|
||||||
ChannelIds = new[] { channelId },
|
|
||||||
ExportFormat = format,
|
|
||||||
OutputPath = filePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
}
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(filePath);
|
// Perform the export only if it hasn't been done before
|
||||||
|
if (!File.Exists(filePath))
|
||||||
|
{
|
||||||
|
await new ExportChannelsCommand
|
||||||
|
{
|
||||||
|
Token = Secrets.DiscordToken,
|
||||||
|
ChannelIds = new[] { channelId },
|
||||||
|
ExportFormat = format,
|
||||||
|
OutputPath = filePath
|
||||||
|
}.ExecuteAsync(console);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return await File.ReadAllTextAsync(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async ValueTask<IHtmlDocument> ExportAsHtmlAsync(Snowflake channelId) => Html.Parse(
|
public static async ValueTask<IHtmlDocument> ExportAsHtmlAsync(Snowflake channelId) => Html.Parse(
|
||||||
|
|
|
@ -38,50 +38,49 @@ internal partial class ExportAssetDownloader
|
||||||
var fileName = GetFileNameFromUrl(url);
|
var fileName = GetFileNameFromUrl(url);
|
||||||
var filePath = Path.Combine(_workingDirPath, fileName);
|
var filePath = Path.Combine(_workingDirPath, fileName);
|
||||||
|
|
||||||
using (await Locker.LockAsync(filePath, cancellationToken))
|
using var _ = await Locker.LockAsync(filePath, cancellationToken);
|
||||||
{
|
|
||||||
if (_pathCache.TryGetValue(url, out var cachedFilePath))
|
|
||||||
return cachedFilePath;
|
|
||||||
|
|
||||||
// Reuse existing files if we're allowed to
|
if (_pathCache.TryGetValue(url, out var cachedFilePath))
|
||||||
if (_reuse && File.Exists(filePath))
|
return cachedFilePath;
|
||||||
return _pathCache[url] = filePath;
|
|
||||||
|
|
||||||
Directory.CreateDirectory(_workingDirPath);
|
|
||||||
|
|
||||||
await Http.ResiliencePolicy.ExecuteAsync(async () =>
|
|
||||||
{
|
|
||||||
// Download the file
|
|
||||||
using var response = await Http.Client.GetAsync(url, cancellationToken);
|
|
||||||
await using (var output = File.Create(filePath))
|
|
||||||
await response.Content.CopyToAsync(output, cancellationToken);
|
|
||||||
|
|
||||||
// Try to set the file date according to the last-modified header
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var lastModified = response.Content.Headers.TryGetValue("Last-Modified")?.Pipe(s =>
|
|
||||||
DateTimeOffset.TryParse(s, CultureInfo.InvariantCulture, DateTimeStyles.None, out var instant)
|
|
||||||
? instant
|
|
||||||
: (DateTimeOffset?)null
|
|
||||||
);
|
|
||||||
|
|
||||||
if (lastModified is not null)
|
|
||||||
{
|
|
||||||
File.SetCreationTimeUtc(filePath, lastModified.Value.UtcDateTime);
|
|
||||||
File.SetLastWriteTimeUtc(filePath, lastModified.Value.UtcDateTime);
|
|
||||||
File.SetLastAccessTimeUtc(filePath, lastModified.Value.UtcDateTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// This can apparently fail for some reason.
|
|
||||||
// Updating the file date is not a critical task, so we'll just ignore exceptions thrown here.
|
|
||||||
// https://github.com/Tyrrrz/DiscordChatExporter/issues/585
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// Reuse existing files if we're allowed to
|
||||||
|
if (_reuse && File.Exists(filePath))
|
||||||
return _pathCache[url] = filePath;
|
return _pathCache[url] = filePath;
|
||||||
}
|
|
||||||
|
Directory.CreateDirectory(_workingDirPath);
|
||||||
|
|
||||||
|
await Http.ResiliencePolicy.ExecuteAsync(async () =>
|
||||||
|
{
|
||||||
|
// Download the file
|
||||||
|
using var response = await Http.Client.GetAsync(url, cancellationToken);
|
||||||
|
await using (var output = File.Create(filePath))
|
||||||
|
await response.Content.CopyToAsync(output, cancellationToken);
|
||||||
|
|
||||||
|
// Try to set the file date according to the last-modified header
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var lastModified = response.Content.Headers.TryGetValue("Last-Modified")?.Pipe(s =>
|
||||||
|
DateTimeOffset.TryParse(s, CultureInfo.InvariantCulture, DateTimeStyles.None, out var instant)
|
||||||
|
? instant
|
||||||
|
: (DateTimeOffset?)null
|
||||||
|
);
|
||||||
|
|
||||||
|
if (lastModified is not null)
|
||||||
|
{
|
||||||
|
File.SetCreationTimeUtc(filePath, lastModified.Value.UtcDateTime);
|
||||||
|
File.SetLastWriteTimeUtc(filePath, lastModified.Value.UtcDateTime);
|
||||||
|
File.SetLastAccessTimeUtc(filePath, lastModified.Value.UtcDateTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// This can apparently fail for some reason.
|
||||||
|
// Updating the file date is not a critical task, so we'll just ignore exceptions thrown here.
|
||||||
|
// https://github.com/Tyrrrz/DiscordChatExporter/issues/585
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return _pathCache[url] = filePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,27 +89,17 @@ internal class ExportContext
|
||||||
|
|
||||||
public Role? TryGetRole(Snowflake id) => _roles.GetValueOrDefault(id);
|
public Role? TryGetRole(Snowflake id) => _roles.GetValueOrDefault(id);
|
||||||
|
|
||||||
public Color? TryGetUserColor(Snowflake id)
|
public IReadOnlyList<Role> GetUserRoles(Snowflake id) => TryGetMember(id)?
|
||||||
{
|
.RoleIds
|
||||||
var memberRoles = GetUserRoles(id);
|
.Select(TryGetRole)
|
||||||
|
.WhereNotNull()
|
||||||
|
.OrderByDescending(r => r.Position)
|
||||||
|
.ToArray() ?? Array.Empty<Role>();
|
||||||
|
|
||||||
return memberRoles?
|
public Color? TryGetUserColor(Snowflake id) => GetUserRoles(id)
|
||||||
.Where(r => r.Color is not null)
|
.Where(r => r.Color is not null)
|
||||||
.Select(r => r.Color)
|
.Select(r => r.Color)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
}
|
|
||||||
|
|
||||||
public IReadOnlyList<Role> GetUserRoles(Snowflake id)
|
|
||||||
{
|
|
||||||
var member = TryGetMember(id);
|
|
||||||
|
|
||||||
return member?
|
|
||||||
.RoleIds
|
|
||||||
.Select(TryGetRole)
|
|
||||||
.WhereNotNull()
|
|
||||||
.OrderByDescending(r => r.Position)
|
|
||||||
.ToArray() ?? Array.Empty<Role>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async ValueTask<string> ResolveAssetUrlAsync(string url, CancellationToken cancellationToken = default)
|
public async ValueTask<string> ResolveAssetUrlAsync(string url, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
@ -122,7 +112,7 @@ internal class ExportContext
|
||||||
var relativeFilePath = Path.GetRelativePath(Request.OutputDirPath, filePath);
|
var relativeFilePath = Path.GetRelativePath(Request.OutputDirPath, filePath);
|
||||||
|
|
||||||
// Prefer relative paths so that the output files can be copied around without breaking references.
|
// Prefer relative paths so that the output files can be copied around without breaking references.
|
||||||
// If the assets path is outside of the export directory, use an absolute path instead.
|
// If the asset directory is outside of the export directory, use an absolute path instead.
|
||||||
var optimalFilePath =
|
var optimalFilePath =
|
||||||
relativeFilePath.StartsWith(".." + Path.DirectorySeparatorChar, StringComparison.Ordinal) ||
|
relativeFilePath.StartsWith(".." + Path.DirectorySeparatorChar, StringComparison.Ordinal) ||
|
||||||
relativeFilePath.StartsWith(".." + Path.AltDirectorySeparatorChar, StringComparison.Ordinal)
|
relativeFilePath.StartsWith(".." + Path.AltDirectorySeparatorChar, StringComparison.Ordinal)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue