Formatting output paths (#472)

pull/490/head
Lucas LaBuff 3 years ago committed by GitHub
parent 915f4c8d9f
commit 77b7977324
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

1
.gitignore vendored

@ -4,6 +4,7 @@
*.userosscache
*.sln.docstates
.idea/
.vs/
# Build results
[Dd]ebug/

@ -117,26 +117,33 @@ namespace DiscordChatExporter.Domain.Discord
{
var response = await GetJsonResponseAsync($"guilds/{guildId}/channels");
var categories = response
var orderedResponse = response
.EnumerateArray()
.ToDictionary(
j => j.GetProperty("id").GetString(),
j => j.GetProperty("name").GetString()
);
.OrderBy(j => j.GetProperty("position").GetInt32())
.ThenBy(j => ulong.Parse(j.GetProperty("id").GetString()));
foreach (var channelJson in response.EnumerateArray())
var categories = orderedResponse
.Where(j => j.GetProperty("type").GetInt32() == (int)ChannelType.GuildCategory)
.Select((j, index) => ChannelCategory.Parse(j, index + 1))
.ToDictionary(j => j.Id.ToString());
var position = 0;
foreach (var channelJson in orderedResponse)
{
var parentId = channelJson.GetPropertyOrNull("parent_id")?.GetString();
var category = !string.IsNullOrWhiteSpace(parentId)
? categories.GetValueOrDefault(parentId)
: null;
var channel = Channel.Parse(channelJson, category);
var channel = Channel.Parse(channelJson, category, position);
// Skip non-text channels
if (!channel.IsTextChannel)
continue;
position++;
yield return channel;
}
}
@ -162,10 +169,11 @@ namespace DiscordChatExporter.Domain.Discord
return response?.Pipe(Member.Parse);
}
private async ValueTask<string> GetChannelCategoryAsync(Snowflake channelParentId)
public async ValueTask<ChannelCategory> GetChannelCategoryAsync(Snowflake channelId)
{
var response = await GetJsonResponseAsync($"channels/{channelParentId}");
return response.GetProperty("name").GetString();
var response = await GetJsonResponseAsync($"channels/{channelId}");
return ChannelCategory.Parse(response);
}
public async ValueTask<Channel> GetChannelAsync(Snowflake channelId)

@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using System.Text.Json;
using DiscordChatExporter.Domain.Discord.Models.Common;
using DiscordChatExporter.Domain.Utilities;
@ -36,56 +37,67 @@ namespace DiscordChatExporter.Domain.Discord.Models
public Snowflake GuildId { get; }
public string Category { get; }
public ChannelCategory Category { get; }
public string Name { get; }
public int Position { get; }
public string? Topic { get; }
public Channel(Snowflake id, ChannelType type, Snowflake guildId, string category, string name, string? topic)
public Channel(Snowflake id, ChannelType type, Snowflake guildId, ChannelCategory? category, string name, int position, string? topic)
{
Id = id;
Type = type;
GuildId = guildId;
Category = category;
Category = category ?? GetDefaultCategory(type);
Name = name;
Position = position;
Topic = topic;
}
public override string ToString() => Name;
}
public partial class Channel
{
private static string GetDefaultCategory(ChannelType channelType) => channelType switch
{
ChannelType.GuildTextChat => "Text",
ChannelType.DirectTextChat => "Private",
ChannelType.DirectGroupTextChat => "Group",
ChannelType.GuildNews => "News",
ChannelType.GuildStore => "Store",
_ => "Default"
};
public static Channel Parse(JsonElement json, string? category = null)
private static ChannelCategory GetDefaultCategory(ChannelType channelType) => new(
Snowflake.Zero,
channelType switch
{
ChannelType.GuildTextChat => "Text",
ChannelType.DirectTextChat => "Private",
ChannelType.DirectGroupTextChat => "Group",
ChannelType.GuildNews => "News",
ChannelType.GuildStore => "Store",
_ => "Default"
},
0
);
public static Channel Parse(JsonElement json, ChannelCategory? category = null, int? position = null)
{
var id = json.GetProperty("id").GetString().Pipe(Snowflake.Parse);
var guildId = json.GetPropertyOrNull("guild_id")?.GetString().Pipe(Snowflake.Parse);
var topic = json.GetPropertyOrNull("topic")?.GetString();
var type = (ChannelType) json.GetProperty("type").GetInt32();
var type = (ChannelType)json.GetProperty("type").GetInt32();
var name =
json.GetPropertyOrNull("name")?.GetString() ??
json.GetPropertyOrNull("recipients")?.EnumerateArray().Select(User.Parse).Select(u => u.Name).JoinToString(", ") ??
id.ToString();
position ??= json.GetProperty("position").GetInt32();
return new Channel(
id,
type,
guildId ?? Guild.DirectMessages.Id,
category ?? GetDefaultCategory(type),
name,
position.Value,
topic
);
}

@ -0,0 +1,48 @@
using System;
using System.Linq;
using System.Text.Json;
using DiscordChatExporter.Domain.Discord.Models.Common;
using DiscordChatExporter.Domain.Utilities;
using JsonExtensions.Reading;
using Tyrrrz.Extensions;
namespace DiscordChatExporter.Domain.Discord.Models
{
public partial class ChannelCategory : IHasId
{
public Snowflake Id { get; }
public string Name { get; }
public int Position { get; }
public ChannelCategory(Snowflake id, string name, int position)
{
Id = id;
Name = name;
Position = position;
}
public override string ToString() => Name;
}
public partial class ChannelCategory
{
public static ChannelCategory Parse(JsonElement json, int? position = null)
{
var id = json.GetProperty("id").GetString().Pipe(Snowflake.Parse);
position ??= json.GetProperty("position").GetInt32();
var name = json.GetPropertyOrNull("name")?.GetString() ??
json.GetPropertyOrNull("recipients")?.EnumerateArray().Select(User.Parse).Select(u => u.Name).JoinToString(", ") ??
id.ToString();
return new ChannelCategory(
id,
name,
position.Value
);
}
}
}

@ -0,0 +1,30 @@
using System.Collections.Generic;
namespace DiscordChatExporter.Domain.Discord.Models.Common
{
public partial class ChannelPositionBasedComparer : IComparer<Channel>
{
public int Compare(Channel? x, Channel? y)
{
int result;
if (x != null)
{
result = x.Position.CompareTo(y?.Position);
}
else if (y != null)
{
result = -y.Position.CompareTo(x?.Position);
}
else
{
result = 0;
}
return result;
}
}
public partial class ChannelPositionBasedComparer
{
public static ChannelPositionBasedComparer Instance { get; } = new();
}
}

@ -1,5 +1,7 @@
using System.IO;
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using DiscordChatExporter.Domain.Discord;
using DiscordChatExporter.Domain.Discord.Models;
using DiscordChatExporter.Domain.Internal;
@ -81,6 +83,26 @@ namespace DiscordChatExporter.Domain.Exporting
Snowflake? after = null,
Snowflake? before = null)
{
// Formats path
outputPath = Regex.Replace(outputPath, "%.", m =>
PathEx.EscapePath(m.Value switch
{
"%g" => guild.Id.ToString(),
"%G" => guild.Name,
"%t" => channel.Category.Id.ToString(),
"%T" => channel.Category.Name,
"%c" => channel.Id.ToString(),
"%C" => channel.Name,
"%p" => channel.Position.ToString(),
"%P" => channel.Category.Position.ToString(),
"%a" => (after ?? Snowflake.Zero).ToDate().ToString("yyyy-MM-dd"),
"%b" => (before?.ToDate() ?? DateTime.Now).ToString("yyyy-MM-dd"),
"%%" => "%",
_ => m.Value
})
);
// Output is a directory
if (Directory.Exists(outputPath) || string.IsNullOrWhiteSpace(Path.GetExtension(outputPath)))
{
@ -102,7 +124,7 @@ namespace DiscordChatExporter.Domain.Exporting
var buffer = new StringBuilder();
// Guild and channel names
buffer.Append($"{guild.Name} - {channel.Category} - {channel.Name} [{channel.Id}]");
buffer.Append($"{guild.Name} - {channel.Category.Name} - {channel.Name} [{channel.Id}]");
// Date range
if (after != null || before != null)

@ -192,7 +192,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers
_writer.WriteStartObject("channel");
_writer.WriteString("id", Context.Request.Channel.Id.ToString());
_writer.WriteString("type", Context.Request.Channel.Type.ToString());
_writer.WriteString("category", Context.Request.Channel.Category);
_writer.WriteString("category", Context.Request.Channel.Category.Name);
_writer.WriteString("name", Context.Request.Channel.Name);
_writer.WriteString("topic", Context.Request.Channel.Topic);
_writer.WriteEndObject();

@ -113,7 +113,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers
{
await _writer.WriteLineAsync('='.Repeat(62));
await _writer.WriteLineAsync($"Guild: {Context.Request.Guild.Name}");
await _writer.WriteLineAsync($"Channel: {Context.Request.Channel.Category} / {Context.Request.Channel.Name}");
await _writer.WriteLineAsync($"Channel: {Context.Request.Channel.Category.Name} / {Context.Request.Channel.Name}");
if (!string.IsNullOrWhiteSpace(Context.Request.Channel.Topic))
await _writer.WriteLineAsync($"Topic: {Context.Request.Channel.Topic}");

@ -30,7 +30,7 @@
<PropertyGroupDescription PropertyName="Category" />
</CollectionViewSource.GroupDescriptions>
<CollectionViewSource.SortDescriptions>
<componentModel:SortDescription Direction="Ascending" PropertyName="Category" />
<componentModel:SortDescription Direction="Ascending" PropertyName="Position" />
<componentModel:SortDescription Direction="Ascending" PropertyName="Name" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>

Loading…
Cancel
Save