mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-03-25 07:55:29 +00:00
Use nullable
This commit is contained in:
@@ -12,10 +12,10 @@ namespace DiscordChatExporter.Core.Services
|
||||
{
|
||||
private User ParseUser(JToken json)
|
||||
{
|
||||
var id = json["id"].Value<string>();
|
||||
var discriminator = json["discriminator"].Value<int>();
|
||||
var name = json["username"].Value<string>();
|
||||
var avatarHash = json["avatar"].Value<string>();
|
||||
var id = json["id"]!.Value<string>();
|
||||
var discriminator = json["discriminator"]!.Value<int>();
|
||||
var name = json["username"]!.Value<string>();
|
||||
var avatarHash = json["avatar"]!.Value<string>();
|
||||
var isBot = json["bot"]?.Value<bool>() ?? false;
|
||||
|
||||
return new User(id, discriminator, name, avatarHash, isBot);
|
||||
@@ -23,9 +23,9 @@ namespace DiscordChatExporter.Core.Services
|
||||
|
||||
private Guild ParseGuild(JToken json)
|
||||
{
|
||||
var id = json["id"].Value<string>();
|
||||
var name = json["name"].Value<string>();
|
||||
var iconHash = json["icon"].Value<string>();
|
||||
var id = json["id"]!.Value<string>();
|
||||
var name = json["name"]!.Value<string>();
|
||||
var iconHash = json["icon"]!.Value<string>();
|
||||
|
||||
return new Guild(id, name, iconHash);
|
||||
}
|
||||
@@ -33,23 +33,23 @@ namespace DiscordChatExporter.Core.Services
|
||||
private Channel ParseChannel(JToken json)
|
||||
{
|
||||
// Get basic data
|
||||
var id = json["id"].Value<string>();
|
||||
var id = json["id"]!.Value<string>();
|
||||
var parentId = json["parent_id"]?.Value<string>();
|
||||
var type = (ChannelType) json["type"].Value<int>();
|
||||
var type = (ChannelType) json["type"]!.Value<int>();
|
||||
var topic = json["topic"]?.Value<string>();
|
||||
|
||||
// Try to extract guild ID
|
||||
var guildId = json["guild_id"]?.Value<string>();
|
||||
|
||||
// If the guild ID is blank, it's direct messages
|
||||
if (guildId.IsNullOrWhiteSpace())
|
||||
if (string.IsNullOrWhiteSpace(guildId))
|
||||
guildId = Guild.DirectMessages.Id;
|
||||
|
||||
// Try to extract name
|
||||
var name = json["name"]?.Value<string>();
|
||||
|
||||
// If the name is blank, it's direct messages
|
||||
if (name.IsNullOrWhiteSpace())
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
name = json["recipients"].Select(ParseUser).Select(u => u.Name).JoinToString(", ");
|
||||
|
||||
return new Channel(id, parentId, guildId, name, topic, type);
|
||||
@@ -57,20 +57,20 @@ namespace DiscordChatExporter.Core.Services
|
||||
|
||||
private Role ParseRole(JToken json)
|
||||
{
|
||||
var id = json["id"].Value<string>();
|
||||
var name = json["name"].Value<string>();
|
||||
var id = json["id"]!.Value<string>();
|
||||
var name = json["name"]!.Value<string>();
|
||||
|
||||
return new Role(id, name);
|
||||
}
|
||||
|
||||
private Attachment ParseAttachment(JToken json)
|
||||
{
|
||||
var id = json["id"].Value<string>();
|
||||
var url = json["url"].Value<string>();
|
||||
var id = json["id"]!.Value<string>();
|
||||
var url = json["url"]!.Value<string>();
|
||||
var width = json["width"]?.Value<int>();
|
||||
var height = json["height"]?.Value<int>();
|
||||
var fileName = json["filename"].Value<string>();
|
||||
var fileSizeBytes = json["size"].Value<long>();
|
||||
var fileName = json["filename"]!.Value<string>();
|
||||
var fileSizeBytes = json["size"]!.Value<long>();
|
||||
|
||||
var fileSize = new FileSize(fileSizeBytes);
|
||||
|
||||
@@ -88,8 +88,8 @@ namespace DiscordChatExporter.Core.Services
|
||||
|
||||
private EmbedField ParseEmbedField(JToken json)
|
||||
{
|
||||
var name = json["name"].Value<string>();
|
||||
var value = json["value"].Value<string>();
|
||||
var name = json["name"]!.Value<string>();
|
||||
var value = json["value"]!.Value<string>();
|
||||
var isInline = json["inline"]?.Value<bool>() ?? false;
|
||||
|
||||
return new EmbedField(name, value, isInline);
|
||||
@@ -106,7 +106,7 @@ namespace DiscordChatExporter.Core.Services
|
||||
|
||||
private EmbedFooter ParseEmbedFooter(JToken json)
|
||||
{
|
||||
var text = json["text"].Value<string>();
|
||||
var text = json["text"]!.Value<string>();
|
||||
var iconUrl = json["icon_url"]?.Value<string>();
|
||||
|
||||
return new EmbedFooter(text, iconUrl);
|
||||
@@ -122,23 +122,23 @@ namespace DiscordChatExporter.Core.Services
|
||||
|
||||
// Get color
|
||||
var color = json["color"] != null
|
||||
? Color.FromArgb(json["color"].Value<int>()).ResetAlpha()
|
||||
? Color.FromArgb(json["color"]!.Value<int>()).ResetAlpha()
|
||||
: Color.FromArgb(79, 84, 92); // default color
|
||||
|
||||
// Get author
|
||||
var author = json["author"] != null ? ParseEmbedAuthor(json["author"]) : null;
|
||||
var author = json["author"] != null ? ParseEmbedAuthor(json["author"]!) : null;
|
||||
|
||||
// Get fields
|
||||
var fields = json["fields"].EmptyIfNull().Select(ParseEmbedField).ToArray();
|
||||
var fields = (json["fields"] ?? Enumerable.Empty<JToken>()).Select(ParseEmbedField).ToArray();
|
||||
|
||||
// Get thumbnail
|
||||
var thumbnail = json["thumbnail"] != null ? ParseEmbedImage(json["thumbnail"]) : null;
|
||||
var thumbnail = json["thumbnail"] != null ? ParseEmbedImage(json["thumbnail"]!) : null;
|
||||
|
||||
// Get image
|
||||
var image = json["image"] != null ? ParseEmbedImage(json["image"]) : null;
|
||||
var image = json["image"] != null ? ParseEmbedImage(json["image"]!) : null;
|
||||
|
||||
// Get footer
|
||||
var footer = json["footer"] != null ? ParseEmbedFooter(json["footer"]) : null;
|
||||
var footer = json["footer"] != null ? ParseEmbedFooter(json["footer"]!) : null;
|
||||
|
||||
return new Embed(title, url, timestamp, color, author, description, fields, thumbnail, image, footer);
|
||||
}
|
||||
@@ -146,7 +146,7 @@ namespace DiscordChatExporter.Core.Services
|
||||
private Emoji ParseEmoji(JToken json)
|
||||
{
|
||||
var id = json["id"]?.Value<string>();
|
||||
var name = json["name"]?.Value<string>();
|
||||
var name = json["name"]!.Value<string>();
|
||||
var isAnimated = json["animated"]?.Value<bool>() ?? false;
|
||||
|
||||
return new Emoji(id, name, isAnimated);
|
||||
@@ -154,8 +154,8 @@ namespace DiscordChatExporter.Core.Services
|
||||
|
||||
private Reaction ParseReaction(JToken json)
|
||||
{
|
||||
var count = json["count"].Value<int>();
|
||||
var emoji = ParseEmoji(json["emoji"]);
|
||||
var count = json["count"]!.Value<int>();
|
||||
var emoji = ParseEmoji(json["emoji"]!);
|
||||
|
||||
return new Reaction(count, emoji);
|
||||
}
|
||||
@@ -163,12 +163,12 @@ namespace DiscordChatExporter.Core.Services
|
||||
private Message ParseMessage(JToken json)
|
||||
{
|
||||
// Get basic data
|
||||
var id = json["id"].Value<string>();
|
||||
var channelId = json["channel_id"].Value<string>();
|
||||
var timestamp = json["timestamp"].Value<DateTime>().ToDateTimeOffset();
|
||||
var id = json["id"]!.Value<string>();
|
||||
var channelId = json["channel_id"]!.Value<string>();
|
||||
var timestamp = json["timestamp"]!.Value<DateTime>().ToDateTimeOffset();
|
||||
var editedTimestamp = json["edited_timestamp"]?.Value<DateTime?>()?.ToDateTimeOffset();
|
||||
var content = json["content"].Value<string>();
|
||||
var type = (MessageType) json["type"].Value<int>();
|
||||
var content = json["content"]!.Value<string>();
|
||||
var type = (MessageType) json["type"]!.Value<int>();
|
||||
|
||||
// Workarounds for non-default types
|
||||
if (type == MessageType.RecipientAdd)
|
||||
@@ -187,22 +187,22 @@ namespace DiscordChatExporter.Core.Services
|
||||
content = "Joined the server.";
|
||||
|
||||
// Get author
|
||||
var author = ParseUser(json["author"]);
|
||||
var author = ParseUser(json["author"]!);
|
||||
|
||||
// Get attachments
|
||||
var attachments = json["attachments"].EmptyIfNull().Select(ParseAttachment).ToArray();
|
||||
var attachments = (json["attachments"] ?? Enumerable.Empty<JToken>()).Select(ParseAttachment).ToArray();
|
||||
|
||||
// Get embeds
|
||||
var embeds = json["embeds"].EmptyIfNull().Select(ParseEmbed).ToArray();
|
||||
var embeds = (json["embeds"] ?? Enumerable.Empty<JToken>()).Select(ParseEmbed).ToArray();
|
||||
|
||||
// Get reactions
|
||||
var reactions = json["reactions"].EmptyIfNull().Select(ParseReaction).ToArray();
|
||||
var reactions = (json["reactions"] ?? Enumerable.Empty<JToken>()).Select(ParseReaction).ToArray();
|
||||
|
||||
// Get mentioned users
|
||||
var mentionedUsers = json["mentions"].EmptyIfNull().Select(ParseUser).ToArray();
|
||||
var mentionedUsers = (json["mentions"] ?? Enumerable.Empty<JToken>()).Select(ParseUser).ToArray();
|
||||
|
||||
// Get whether this message is pinned
|
||||
var isPinned = json["pinned"].Value<bool>();
|
||||
var isPinned = json["pinned"]!.Value<bool>();
|
||||
|
||||
return new Message(id, channelId, type, author, timestamp, editedTimestamp, content, attachments, embeds,
|
||||
reactions, mentionedUsers, isPinned);
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace DiscordChatExporter.Core.Services
|
||||
var value = parameter.SubstringAfter("=");
|
||||
|
||||
// Skip empty values
|
||||
if (value.IsNullOrWhiteSpace())
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
continue;
|
||||
|
||||
request.RequestUri = request.RequestUri.SetQueryParameter(key, value);
|
||||
@@ -53,6 +53,7 @@ namespace DiscordChatExporter.Core.Services
|
||||
|
||||
// Get response
|
||||
using var response = await _httpClient.SendAsync(request);
|
||||
|
||||
// Check status code
|
||||
// We throw our own exception here because default one doesn't have status code
|
||||
if (!response.IsSuccessStatusCode)
|
||||
@@ -119,7 +120,7 @@ namespace DiscordChatExporter.Core.Services
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<Message>> GetChannelMessagesAsync(AuthToken token, string channelId,
|
||||
DateTimeOffset? after = null, DateTimeOffset? before = null, IProgress<double> progress = null)
|
||||
DateTimeOffset? after = null, DateTimeOffset? before = null, IProgress<double>? progress = null)
|
||||
{
|
||||
var result = new List<Message>();
|
||||
|
||||
@@ -211,7 +212,7 @@ namespace DiscordChatExporter.Core.Services
|
||||
}
|
||||
|
||||
public async Task<ChatLog> GetChatLogAsync(AuthToken token, Guild guild, Channel channel,
|
||||
DateTimeOffset? after = null, DateTimeOffset? before = null, IProgress<double> progress = null)
|
||||
DateTimeOffset? after = null, DateTimeOffset? before = null, IProgress<double>? progress = null)
|
||||
{
|
||||
// Get messages
|
||||
var messages = await GetChannelMessagesAsync(token, channel.Id, after, before, progress);
|
||||
@@ -223,19 +224,19 @@ namespace DiscordChatExporter.Core.Services
|
||||
}
|
||||
|
||||
public async Task<ChatLog> GetChatLogAsync(AuthToken token, Channel channel,
|
||||
DateTimeOffset? after = null, DateTimeOffset? before = null, IProgress<double> progress = null)
|
||||
DateTimeOffset? after = null, DateTimeOffset? before = null, IProgress<double>? progress = null)
|
||||
{
|
||||
// Get guild
|
||||
var guild = channel.GuildId == Guild.DirectMessages.Id
|
||||
? Guild.DirectMessages
|
||||
: await GetGuildAsync(token, channel.GuildId);
|
||||
var guild = !string.IsNullOrWhiteSpace(channel.GuildId)
|
||||
? await GetGuildAsync(token, channel.GuildId)
|
||||
: Guild.DirectMessages;
|
||||
|
||||
// Get the chat log
|
||||
return await GetChatLogAsync(token, guild, channel, after, before, progress);
|
||||
}
|
||||
|
||||
public async Task<ChatLog> GetChatLogAsync(AuthToken token, string channelId,
|
||||
DateTimeOffset? after = null, DateTimeOffset? before = null, IProgress<double> progress = null)
|
||||
DateTimeOffset? after = null, DateTimeOffset? before = null, IProgress<double>? progress = null)
|
||||
{
|
||||
// Get channel
|
||||
var channel = await GetChannelAsync(token, channelId);
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Failsafe" Version="1.1.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
<PackageReference Include="Onova" Version="2.4.5" />
|
||||
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.3" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="Onova" Version="2.5.1" />
|
||||
<PackageReference Include="Tyrrrz.Extensions" Version="1.6.5" />
|
||||
<PackageReference Include="Tyrrrz.Settings" Version="1.3.4" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace DiscordChatExporter.Core.Services
|
||||
{
|
||||
// Create output directory
|
||||
var dirPath = Path.GetDirectoryName(filePath);
|
||||
if (!dirPath.IsNullOrWhiteSpace())
|
||||
if (!string.IsNullOrWhiteSpace(dirPath))
|
||||
Directory.CreateDirectory(dirPath);
|
||||
|
||||
// Render chat log to output file
|
||||
@@ -74,7 +74,7 @@ namespace DiscordChatExporter.Core.Services
|
||||
var partitionFilePath = $"{fileNameWithoutExt} [{partitionNumber} of {partitions.Length}]{fileExt}";
|
||||
|
||||
// Compose full file path
|
||||
if (!dirPath.IsNullOrWhiteSpace())
|
||||
if (!string.IsNullOrWhiteSpace(dirPath))
|
||||
partitionFilePath = Path.Combine(dirPath, partitionFilePath);
|
||||
|
||||
// Export
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using DiscordChatExporter.Core.Models;
|
||||
using Tyrrrz.Extensions;
|
||||
|
||||
namespace DiscordChatExporter.Core.Services.Helpers
|
||||
{
|
||||
@@ -12,7 +11,7 @@ namespace DiscordChatExporter.Core.Services.Helpers
|
||||
public static bool IsDirectoryPath(string path) =>
|
||||
path.Last() == Path.DirectorySeparatorChar ||
|
||||
path.Last() == Path.AltDirectorySeparatorChar ||
|
||||
Path.GetExtension(path).IsNullOrWhiteSpace() && !File.Exists(path);
|
||||
string.IsNullOrWhiteSpace(Path.GetExtension(path)) && !File.Exists(path);
|
||||
|
||||
public static string GetDefaultExportFileName(ExportFormat format, Guild guild, Channel channel,
|
||||
DateTimeOffset? after = null, DateTimeOffset? before = null)
|
||||
|
||||
@@ -9,8 +9,10 @@ namespace DiscordChatExporter.Core.Services
|
||||
|
||||
public string DateFormat { get; set; } = "dd-MMM-yy hh:mm tt";
|
||||
|
||||
public AuthToken LastToken { get; set; }
|
||||
public AuthToken? LastToken { get; set; }
|
||||
|
||||
public ExportFormat LastExportFormat { get; set; } = ExportFormat.HtmlDark;
|
||||
|
||||
public int? LastPartitionLimit { get; set; }
|
||||
|
||||
public SettingsService()
|
||||
|
||||
Reference in New Issue
Block a user