mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2025-06-01 07:18:23 -04:00
Formatting output paths (#472)
This commit is contained in:
parent
915f4c8d9f
commit
77b7977324
9 changed files with 152 additions and 31 deletions
1
.gitignore
vendored
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"
|
||||
};
|
||||
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, string? category = null)
|
||||
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
|
||||
);
|
||||
}
|
||||
|
|
48
DiscordChatExporter.Domain/Discord/Models/ChannelCategory.cs
Normal file
48
DiscordChatExporter.Domain/Discord/Models/ChannelCategory.cs
Normal file
|
@ -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…
Add table
Add a link
Reference in a new issue