mirror of
https://github.com/chylex/Discord-History-Tracker.git
synced 2025-07-15 23:51:01 +03:00
Compare commits
7 Commits
6d3db23f80
...
6f1149ad5e
Author | SHA1 | Date | |
---|---|---|---|
|
6f1149ad5e | ||
|
b9899922e0 | ||
|
6a2933ea0a | ||
|
be5c76c3bd | ||
|
217c1f9e10 | ||
|
725ab7accf | ||
|
9a7a2cffc2 |
@ -15,12 +15,25 @@ namespace DHT.Desktop {
|
|||||||
for (int i = 0; i < args.Length; i++) {
|
for (int i = 0; i < args.Length; i++) {
|
||||||
string key = args[i];
|
string key = args[i];
|
||||||
|
|
||||||
if (i >= args.Length - 1) {
|
switch (key) {
|
||||||
|
case "-debug":
|
||||||
|
Log.IsDebugEnabled = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string value;
|
||||||
|
|
||||||
|
if (i == 0 && !key.StartsWith('-')) {
|
||||||
|
value = key;
|
||||||
|
key = "-db";
|
||||||
|
}
|
||||||
|
else if (i >= args.Length - 1) {
|
||||||
Log.Warn("Missing value for command line argument: " + key);
|
Log.Warn("Missing value for command line argument: " + key);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
string value = args[++i];
|
value = args[++i];
|
||||||
|
}
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case "-db":
|
case "-db":
|
||||||
|
@ -56,11 +56,11 @@ namespace DHT.Desktop.Common {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<DialogResult.YesNo> ShowCanUpgradeDatabaseDialog(Window window) {
|
public static async Task<DialogResult.YesNo> ShowCanUpgradeDatabaseDialog(Window window) {
|
||||||
return await Dialog.ShowYesNo(window, "Database Upgrade", "This database was created with an older version of DHT. If you proceed, the database will be upgraded and will no longer open in previous versions of DHT. Do you want to proceed with the upgrade?");
|
return await Dialog.ShowYesNo(window, "Database Upgrade", "This database was created with an older version of DHT. If you proceed, the database will be upgraded and will no longer open in previous versions of DHT.\n\nPlease ensure you have a backup of the database. Do you want to proceed with the upgrade?");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<DialogResult.YesNo> ShowCanUpgradeMultipleDatabaseDialog(Window window) {
|
public static async Task<DialogResult.YesNo> ShowCanUpgradeMultipleDatabaseDialog(Window window) {
|
||||||
return await Dialog.ShowYesNo(window, "Database Upgrade", "One or more databases were created with an older version of DHT. If you proceed, these databases will be upgraded and will no longer open in previous versions of DHT. Otherwise, these databases will be skipped. Do you want to proceed with the upgrade?");
|
return await Dialog.ShowYesNo(window, "Database Upgrade", "One or more databases were created with an older version of DHT. If you proceed, these databases will be upgraded and will no longer open in previous versions of DHT. Otherwise, these databases will be skipped.\n\nPlease ensure you have a backup of the databases. Do you want to proceed with the upgrade?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Dynamic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using DHT.Server.Data;
|
using DHT.Server.Data;
|
||||||
using DHT.Server.Data.Filters;
|
using DHT.Server.Data.Filters;
|
||||||
|
using DHT.Utils.Logging;
|
||||||
|
|
||||||
namespace DHT.Server.Database.Export {
|
namespace DHT.Server.Database.Export {
|
||||||
public static class ViewerJsonExport {
|
public static class ViewerJsonExport {
|
||||||
|
private static readonly Log Log = Log.ForType(typeof(ViewerJsonExport));
|
||||||
|
|
||||||
public static string Generate(IDatabaseFile db, MessageFilter? filter = null) {
|
public static string Generate(IDatabaseFile db, MessageFilter? filter = null) {
|
||||||
|
var perf = Log.Start();
|
||||||
|
|
||||||
var includedUserIds = new HashSet<ulong>();
|
var includedUserIds = new HashSet<ulong>();
|
||||||
var includedChannelIds = new HashSet<ulong>();
|
var includedChannelIds = new HashSet<ulong>();
|
||||||
var includedServerIds = new HashSet<ulong>();
|
var includedServerIds = new HashSet<ulong>();
|
||||||
@ -34,16 +38,19 @@ namespace DHT.Server.Database.Export {
|
|||||||
var servers = GenerateServerList(db, includedServerIds, out var serverindex);
|
var servers = GenerateServerList(db, includedServerIds, out var serverindex);
|
||||||
var channels = GenerateChannelList(includedChannels, serverindex);
|
var channels = GenerateChannelList(includedChannels, serverindex);
|
||||||
|
|
||||||
return JsonSerializer.Serialize(new {
|
var json = JsonSerializer.Serialize(new {
|
||||||
meta = new { users, userindex, servers, channels },
|
meta = new { users, userindex, servers, channels },
|
||||||
data = GenerateMessageList(includedMessages, userIndices)
|
data = GenerateMessageList(includedMessages, userIndices)
|
||||||
}, opts);
|
}, opts);
|
||||||
|
|
||||||
|
perf.End();
|
||||||
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static dynamic GenerateUserList(IDatabaseFile db, HashSet<ulong> userIds, out List<string> userindex, out Dictionary<ulong, int> userIndices) {
|
private static object GenerateUserList(IDatabaseFile db, HashSet<ulong> userIds, out List<string> userindex, out Dictionary<ulong, object> userIndices) {
|
||||||
var users = new Dictionary<string, dynamic>();
|
var users = new Dictionary<string, object>();
|
||||||
userindex = new List<string>();
|
userindex = new List<string>();
|
||||||
userIndices = new Dictionary<ulong, int>();
|
userIndices = new Dictionary<ulong, object>();
|
||||||
|
|
||||||
foreach (var user in db.GetAllUsers()) {
|
foreach (var user in db.GetAllUsers()) {
|
||||||
var id = user.Id;
|
var id = user.Id;
|
||||||
@ -51,15 +58,16 @@ namespace DHT.Server.Database.Export {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic obj = new ExpandoObject();
|
var obj = new Dictionary<string, object> {
|
||||||
obj.name = user.Name;
|
["name"] = user.Name
|
||||||
|
};
|
||||||
|
|
||||||
if (user.AvatarUrl != null) {
|
if (user.AvatarUrl != null) {
|
||||||
obj.avatar = user.AvatarUrl;
|
obj["avatar"] = user.AvatarUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.Discriminator != null) {
|
if (user.Discriminator != null) {
|
||||||
obj.tag = user.Discriminator;
|
obj["tag"] = user.Discriminator;
|
||||||
}
|
}
|
||||||
|
|
||||||
var idStr = id.ToString();
|
var idStr = id.ToString();
|
||||||
@ -71,9 +79,9 @@ namespace DHT.Server.Database.Export {
|
|||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static dynamic GenerateServerList(IDatabaseFile db, HashSet<ulong> serverIds, out Dictionary<ulong, int> serverIndices) {
|
private static object GenerateServerList(IDatabaseFile db, HashSet<ulong> serverIds, out Dictionary<ulong, object> serverIndices) {
|
||||||
var servers = new List<dynamic>();
|
var servers = new List<object>();
|
||||||
serverIndices = new Dictionary<ulong, int>();
|
serverIndices = new Dictionary<ulong, object>();
|
||||||
|
|
||||||
foreach (var server in db.GetAllServers()) {
|
foreach (var server in db.GetAllServers()) {
|
||||||
var id = server.Id;
|
var id = server.Id;
|
||||||
@ -82,37 +90,38 @@ namespace DHT.Server.Database.Export {
|
|||||||
}
|
}
|
||||||
|
|
||||||
serverIndices[id] = servers.Count;
|
serverIndices[id] = servers.Count;
|
||||||
servers.Add(new {
|
servers.Add(new Dictionary<string, object> {
|
||||||
name = server.Name,
|
["name"] = server.Name,
|
||||||
type = ServerTypes.ToJsonViewerString(server.Type)
|
["type"] = ServerTypes.ToJsonViewerString(server.Type)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return servers;
|
return servers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static dynamic GenerateChannelList(List<Channel> includedChannels, Dictionary<ulong, int> serverIndices) {
|
private static object GenerateChannelList(List<Channel> includedChannels, Dictionary<ulong, object> serverIndices) {
|
||||||
var channels = new Dictionary<string, dynamic>();
|
var channels = new Dictionary<string, object>();
|
||||||
|
|
||||||
foreach (var channel in includedChannels) {
|
foreach (var channel in includedChannels) {
|
||||||
dynamic obj = new ExpandoObject();
|
var obj = new Dictionary<string, object> {
|
||||||
obj.server = serverIndices[channel.Server];
|
["server"] = serverIndices[channel.Server],
|
||||||
obj.name = channel.Name;
|
["name"] = channel.Name
|
||||||
|
};
|
||||||
|
|
||||||
if (channel.ParentId != null) {
|
if (channel.ParentId != null) {
|
||||||
obj.parent = channel.ParentId;
|
obj["parent"] = channel.ParentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel.Position != null) {
|
if (channel.Position != null) {
|
||||||
obj.position = channel.Position;
|
obj["position"] = channel.Position;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel.Topic != null) {
|
if (channel.Topic != null) {
|
||||||
obj.topic = channel.Topic;
|
obj["topic"] = channel.Topic;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel.Nsfw != null) {
|
if (channel.Nsfw != null) {
|
||||||
obj.nsfw = channel.Nsfw;
|
obj["nsfw"] = channel.Nsfw;
|
||||||
}
|
}
|
||||||
|
|
||||||
channels[channel.Id.ToString()] = obj;
|
channels[channel.Id.ToString()] = obj;
|
||||||
@ -121,54 +130,55 @@ namespace DHT.Server.Database.Export {
|
|||||||
return channels;
|
return channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static dynamic GenerateMessageList(List<Message> includedMessages, Dictionary<ulong, int> userIndices) {
|
private static object GenerateMessageList(List<Message> includedMessages, Dictionary<ulong, object> userIndices) {
|
||||||
var data = new Dictionary<string, Dictionary<string, dynamic>>();
|
var data = new Dictionary<string, Dictionary<string, object>>();
|
||||||
|
|
||||||
foreach (var grouping in includedMessages.GroupBy(static message => message.Channel)) {
|
foreach (var grouping in includedMessages.GroupBy(static message => message.Channel)) {
|
||||||
var channel = grouping.Key.ToString();
|
var channel = grouping.Key.ToString();
|
||||||
var channelData = new Dictionary<string, dynamic>();
|
var channelData = new Dictionary<string, object>();
|
||||||
|
|
||||||
foreach (var message in grouping) {
|
foreach (var message in grouping) {
|
||||||
dynamic obj = new ExpandoObject();
|
var obj = new Dictionary<string, object> {
|
||||||
obj.u = userIndices[message.Sender];
|
["u"] = userIndices[message.Sender],
|
||||||
obj.t = message.Timestamp;
|
["t"] = message.Timestamp
|
||||||
|
};
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(message.Text)) {
|
if (!string.IsNullOrEmpty(message.Text)) {
|
||||||
obj.m = message.Text;
|
obj["m"] = message.Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.EditTimestamp != null) {
|
if (message.EditTimestamp != null) {
|
||||||
obj.te = message.EditTimestamp;
|
obj["te"] = message.EditTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.RepliedToId != null) {
|
if (message.RepliedToId != null) {
|
||||||
obj.r = message.RepliedToId.Value;
|
obj["r"] = message.RepliedToId.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!message.Attachments.IsEmpty) {
|
if (!message.Attachments.IsEmpty) {
|
||||||
obj.a = message.Attachments.Select(static attachment => new {
|
obj["a"] = message.Attachments.Select(static attachment => new {
|
||||||
url = attachment.Url
|
url = attachment.Url
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!message.Embeds.IsEmpty) {
|
if (!message.Embeds.IsEmpty) {
|
||||||
obj.e = message.Embeds.Select(static embed => embed.Json).ToArray();
|
obj["e"] = message.Embeds.Select(static embed => embed.Json).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!message.Reactions.IsEmpty) {
|
if (!message.Reactions.IsEmpty) {
|
||||||
obj.re = message.Reactions.Select(static reaction => {
|
obj["re"] = message.Reactions.Select(static reaction => {
|
||||||
dynamic r = new ExpandoObject();
|
var r = new Dictionary<string, object>();
|
||||||
|
|
||||||
if (reaction.EmojiId != null) {
|
if (reaction.EmojiId != null) {
|
||||||
r.id = reaction.EmojiId.Value;
|
r["id"] = reaction.EmojiId.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reaction.EmojiName != null) {
|
if (reaction.EmojiName != null) {
|
||||||
r.n = reaction.EmojiName;
|
r["n"] = reaction.EmojiName;
|
||||||
}
|
}
|
||||||
|
|
||||||
r.a = reaction.EmojiFlags.HasFlag(EmojiFlags.Animated);
|
r["a"] = reaction.EmojiFlags.HasFlag(EmojiFlags.Animated);
|
||||||
r.c = reaction.Count;
|
r["c"] = reaction.Count;
|
||||||
return r;
|
return r;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ namespace DHT.Server.Database.Sqlite {
|
|||||||
public async Task<bool> Setup(Func<Task<bool>> checkCanUpgradeSchemas) {
|
public async Task<bool> Setup(Func<Task<bool>> checkCanUpgradeSchemas) {
|
||||||
Execute(@"CREATE TABLE IF NOT EXISTS metadata (key TEXT PRIMARY KEY, value TEXT)");
|
Execute(@"CREATE TABLE IF NOT EXISTS metadata (key TEXT PRIMARY KEY, value TEXT)");
|
||||||
|
|
||||||
var dbVersionStr = Sql("SELECT value FROM metadata WHERE key = 'version'").ExecuteScalar();
|
var dbVersionStr = conn.SelectScalar("SELECT value FROM metadata WHERE key = 'version'");
|
||||||
if (dbVersionStr == null) {
|
if (dbVersionStr == null) {
|
||||||
InitializeSchemas();
|
InitializeSchemas();
|
||||||
}
|
}
|
||||||
|
@ -43,13 +43,14 @@ namespace DHT.Server.Database.Sqlite {
|
|||||||
|
|
||||||
public void AddServer(Data.Server server) {
|
public void AddServer(Data.Server server) {
|
||||||
using var cmd = conn.Upsert("servers", new[] {
|
using var cmd = conn.Upsert("servers", new[] {
|
||||||
"id", "name", "type"
|
("id", SqliteType.Integer),
|
||||||
|
("name", SqliteType.Text),
|
||||||
|
("type", SqliteType.Text)
|
||||||
});
|
});
|
||||||
|
|
||||||
var serverParams = cmd.Parameters;
|
cmd.Set(":id", server.Id);
|
||||||
serverParams.AddAndSet(":id", server.Id);
|
cmd.Set(":name", server.Name);
|
||||||
serverParams.AddAndSet(":name", server.Name);
|
cmd.Set(":type", ServerTypes.ToString(server.Type));
|
||||||
serverParams.AddAndSet(":type", ServerTypes.ToString(server.Type));
|
|
||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
UpdateServerStatistics();
|
UpdateServerStatistics();
|
||||||
}
|
}
|
||||||
@ -62,7 +63,7 @@ namespace DHT.Server.Database.Sqlite {
|
|||||||
|
|
||||||
while (reader.Read()) {
|
while (reader.Read()) {
|
||||||
list.Add(new Data.Server {
|
list.Add(new Data.Server {
|
||||||
Id = (ulong) reader.GetInt64(0),
|
Id = reader.GetUint64(0),
|
||||||
Name = reader.GetString(1),
|
Name = reader.GetString(1),
|
||||||
Type = ServerTypes.FromString(reader.GetString(2))
|
Type = ServerTypes.FromString(reader.GetString(2))
|
||||||
});
|
});
|
||||||
@ -73,17 +74,22 @@ namespace DHT.Server.Database.Sqlite {
|
|||||||
|
|
||||||
public void AddChannel(Channel channel) {
|
public void AddChannel(Channel channel) {
|
||||||
using var cmd = conn.Upsert("channels", new[] {
|
using var cmd = conn.Upsert("channels", new[] {
|
||||||
"id", "server", "name", "parent_id", "position", "topic", "nsfw"
|
("id", SqliteType.Integer),
|
||||||
|
("server", SqliteType.Integer),
|
||||||
|
("name", SqliteType.Text),
|
||||||
|
("parent_id", SqliteType.Integer),
|
||||||
|
("position", SqliteType.Integer),
|
||||||
|
("topic", SqliteType.Text),
|
||||||
|
("nsfw", SqliteType.Integer)
|
||||||
});
|
});
|
||||||
|
|
||||||
var channelParams = cmd.Parameters;
|
cmd.Set(":id", channel.Id);
|
||||||
channelParams.AddAndSet(":id", channel.Id);
|
cmd.Set(":server", channel.Server);
|
||||||
channelParams.AddAndSet(":server", channel.Server);
|
cmd.Set(":name", channel.Name);
|
||||||
channelParams.AddAndSet(":name", channel.Name);
|
cmd.Set(":parent_id", channel.ParentId);
|
||||||
channelParams.AddAndSet(":parent_id", channel.ParentId);
|
cmd.Set(":position", channel.Position);
|
||||||
channelParams.AddAndSet(":position", channel.Position);
|
cmd.Set(":topic", channel.Topic);
|
||||||
channelParams.AddAndSet(":topic", channel.Topic);
|
cmd.Set(":nsfw", channel.Nsfw);
|
||||||
channelParams.AddAndSet(":nsfw", channel.Nsfw);
|
|
||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
UpdateChannelStatistics();
|
UpdateChannelStatistics();
|
||||||
}
|
}
|
||||||
@ -96,10 +102,10 @@ namespace DHT.Server.Database.Sqlite {
|
|||||||
|
|
||||||
while (reader.Read()) {
|
while (reader.Read()) {
|
||||||
list.Add(new Channel {
|
list.Add(new Channel {
|
||||||
Id = (ulong) reader.GetInt64(0),
|
Id = reader.GetUint64(0),
|
||||||
Server = (ulong) reader.GetInt64(1),
|
Server = reader.GetUint64(1),
|
||||||
Name = reader.GetString(2),
|
Name = reader.GetString(2),
|
||||||
ParentId = reader.IsDBNull(3) ? null : (ulong) reader.GetInt64(3),
|
ParentId = reader.IsDBNull(3) ? null : reader.GetUint64(3),
|
||||||
Position = reader.IsDBNull(4) ? null : reader.GetInt32(4),
|
Position = reader.IsDBNull(4) ? null : reader.GetInt32(4),
|
||||||
Topic = reader.IsDBNull(5) ? null : reader.GetString(5),
|
Topic = reader.IsDBNull(5) ? null : reader.GetString(5),
|
||||||
Nsfw = reader.IsDBNull(6) ? null : reader.GetBoolean(6)
|
Nsfw = reader.IsDBNull(6) ? null : reader.GetBoolean(6)
|
||||||
@ -112,20 +118,17 @@ namespace DHT.Server.Database.Sqlite {
|
|||||||
public void AddUsers(User[] users) {
|
public void AddUsers(User[] users) {
|
||||||
using var tx = conn.BeginTransaction();
|
using var tx = conn.BeginTransaction();
|
||||||
using var cmd = conn.Upsert("users", new[] {
|
using var cmd = conn.Upsert("users", new[] {
|
||||||
"id", "name", "avatar_url", "discriminator"
|
("id", SqliteType.Integer),
|
||||||
|
("name", SqliteType.Text),
|
||||||
|
("avatar_url", SqliteType.Text),
|
||||||
|
("discriminator", SqliteType.Text)
|
||||||
});
|
});
|
||||||
|
|
||||||
var userParams = cmd.Parameters;
|
|
||||||
userParams.Add(":id", SqliteType.Integer);
|
|
||||||
userParams.Add(":name", SqliteType.Text);
|
|
||||||
userParams.Add(":avatar_url", SqliteType.Text);
|
|
||||||
userParams.Add(":discriminator", SqliteType.Text);
|
|
||||||
|
|
||||||
foreach (var user in users) {
|
foreach (var user in users) {
|
||||||
userParams.Set(":id", user.Id);
|
cmd.Set(":id", user.Id);
|
||||||
userParams.Set(":name", user.Name);
|
cmd.Set(":name", user.Name);
|
||||||
userParams.Set(":avatar_url", user.AvatarUrl);
|
cmd.Set(":avatar_url", user.AvatarUrl);
|
||||||
userParams.Set(":discriminator", user.Discriminator);
|
cmd.Set(":discriminator", user.Discriminator);
|
||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +144,7 @@ namespace DHT.Server.Database.Sqlite {
|
|||||||
|
|
||||||
while (reader.Read()) {
|
while (reader.Read()) {
|
||||||
list.Add(new User {
|
list.Add(new User {
|
||||||
Id = (ulong) reader.GetInt64(0),
|
Id = reader.GetUint64(0),
|
||||||
Name = reader.GetString(1),
|
Name = reader.GetString(1),
|
||||||
AvatarUrl = reader.IsDBNull(2) ? null : reader.GetString(2),
|
AvatarUrl = reader.IsDBNull(2) ? null : reader.GetString(2),
|
||||||
Discriminator = reader.IsDBNull(3) ? null : reader.GetString(3)
|
Discriminator = reader.IsDBNull(3) ? null : reader.GetString(3)
|
||||||
@ -153,110 +156,91 @@ namespace DHT.Server.Database.Sqlite {
|
|||||||
|
|
||||||
public void AddMessages(Message[] messages) {
|
public void AddMessages(Message[] messages) {
|
||||||
using var tx = conn.BeginTransaction();
|
using var tx = conn.BeginTransaction();
|
||||||
|
|
||||||
using var messageCmd = conn.Upsert("messages", new[] {
|
using var messageCmd = conn.Upsert("messages", new[] {
|
||||||
"message_id", "sender_id", "channel_id", "text", "timestamp", "edit_timestamp", "replied_to_id"
|
("message_id", SqliteType.Integer),
|
||||||
|
("sender_id", SqliteType.Integer),
|
||||||
|
("channel_id", SqliteType.Integer),
|
||||||
|
("text", SqliteType.Text),
|
||||||
|
("timestamp", SqliteType.Integer),
|
||||||
|
("edit_timestamp", SqliteType.Integer),
|
||||||
|
("replied_to_id", SqliteType.Integer)
|
||||||
});
|
});
|
||||||
|
|
||||||
using var deleteAttachmentsCmd = conn.Command("DELETE FROM attachments WHERE message_id = :message_id");
|
using var deleteAttachmentsCmd = conn.Delete("attachments", ("message_id", SqliteType.Integer));
|
||||||
|
using var deleteEmbedsCmd = conn.Delete("embeds", ("message_id", SqliteType.Integer));
|
||||||
|
using var deleteReactionsCmd = conn.Delete("reactions", ("message_id", SqliteType.Integer));
|
||||||
|
|
||||||
using var attachmentCmd = conn.Insert("attachments", new[] {
|
using var attachmentCmd = conn.Insert("attachments", new[] {
|
||||||
"message_id", "attachment_id", "name", "type", "url", "size"
|
("message_id", SqliteType.Integer),
|
||||||
|
("attachment_id", SqliteType.Integer),
|
||||||
|
("name", SqliteType.Text),
|
||||||
|
("type", SqliteType.Text),
|
||||||
|
("url", SqliteType.Text),
|
||||||
|
("size", SqliteType.Integer)
|
||||||
});
|
});
|
||||||
|
|
||||||
using var deleteEmbedsCmd = conn.Command("DELETE FROM embeds WHERE message_id = :message_id");
|
|
||||||
using var embedCmd = conn.Insert("embeds", new[] {
|
using var embedCmd = conn.Insert("embeds", new[] {
|
||||||
"message_id", "json"
|
("message_id", SqliteType.Integer),
|
||||||
|
("json", SqliteType.Text)
|
||||||
});
|
});
|
||||||
|
|
||||||
using var deleteReactionsCmd = conn.Command("DELETE FROM reactions WHERE message_id = :message_id");
|
|
||||||
using var reactionCmd = conn.Insert("reactions", new[] {
|
using var reactionCmd = conn.Insert("reactions", new[] {
|
||||||
"message_id", "emoji_id", "emoji_name", "emoji_flags", "count"
|
("message_id", SqliteType.Integer),
|
||||||
|
("emoji_id", SqliteType.Integer),
|
||||||
|
("emoji_name", SqliteType.Text),
|
||||||
|
("emoji_flags", SqliteType.Integer),
|
||||||
|
("count", SqliteType.Integer)
|
||||||
});
|
});
|
||||||
|
|
||||||
var messageParams = messageCmd.Parameters;
|
|
||||||
messageParams.Add(":message_id", SqliteType.Integer);
|
|
||||||
messageParams.Add(":sender_id", SqliteType.Integer);
|
|
||||||
messageParams.Add(":channel_id", SqliteType.Integer);
|
|
||||||
messageParams.Add(":text", SqliteType.Text);
|
|
||||||
messageParams.Add(":timestamp", SqliteType.Integer);
|
|
||||||
messageParams.Add(":edit_timestamp", SqliteType.Integer);
|
|
||||||
messageParams.Add(":replied_to_id", SqliteType.Integer);
|
|
||||||
|
|
||||||
var deleteAttachmentsParams = deleteAttachmentsCmd.Parameters;
|
|
||||||
deleteAttachmentsParams.Add(":message_id", SqliteType.Integer);
|
|
||||||
|
|
||||||
var attachmentParams = attachmentCmd.Parameters;
|
|
||||||
attachmentParams.Add(":message_id", SqliteType.Integer);
|
|
||||||
attachmentParams.Add(":attachment_id", SqliteType.Integer);
|
|
||||||
attachmentParams.Add(":name", SqliteType.Text);
|
|
||||||
attachmentParams.Add(":type", SqliteType.Text);
|
|
||||||
attachmentParams.Add(":url", SqliteType.Text);
|
|
||||||
attachmentParams.Add(":size", SqliteType.Integer);
|
|
||||||
|
|
||||||
var deleteEmbedsParams = deleteEmbedsCmd.Parameters;
|
|
||||||
deleteEmbedsParams.Add(":message_id", SqliteType.Integer);
|
|
||||||
|
|
||||||
var embedParams = embedCmd.Parameters;
|
|
||||||
embedParams.Add(":message_id", SqliteType.Integer);
|
|
||||||
embedParams.Add(":json", SqliteType.Text);
|
|
||||||
|
|
||||||
var deleteReactionsParams = deleteReactionsCmd.Parameters;
|
|
||||||
deleteReactionsParams.Add(":message_id", SqliteType.Integer);
|
|
||||||
|
|
||||||
var reactionParams = reactionCmd.Parameters;
|
|
||||||
reactionParams.Add(":message_id", SqliteType.Integer);
|
|
||||||
reactionParams.Add(":emoji_id", SqliteType.Integer);
|
|
||||||
reactionParams.Add(":emoji_name", SqliteType.Text);
|
|
||||||
reactionParams.Add(":emoji_flags", SqliteType.Integer);
|
|
||||||
reactionParams.Add(":count", SqliteType.Integer);
|
|
||||||
|
|
||||||
foreach (var message in messages) {
|
foreach (var message in messages) {
|
||||||
object messageId = message.Id;
|
object messageId = message.Id;
|
||||||
|
|
||||||
messageParams.Set(":message_id", messageId);
|
messageCmd.Set(":message_id", messageId);
|
||||||
messageParams.Set(":sender_id", message.Sender);
|
messageCmd.Set(":sender_id", message.Sender);
|
||||||
messageParams.Set(":channel_id", message.Channel);
|
messageCmd.Set(":channel_id", message.Channel);
|
||||||
messageParams.Set(":text", message.Text);
|
messageCmd.Set(":text", message.Text);
|
||||||
messageParams.Set(":timestamp", message.Timestamp);
|
messageCmd.Set(":timestamp", message.Timestamp);
|
||||||
messageParams.Set(":edit_timestamp", message.EditTimestamp);
|
messageCmd.Set(":edit_timestamp", message.EditTimestamp);
|
||||||
messageParams.Set(":replied_to_id", message.RepliedToId);
|
messageCmd.Set(":replied_to_id", message.RepliedToId);
|
||||||
messageCmd.ExecuteNonQuery();
|
messageCmd.ExecuteNonQuery();
|
||||||
|
|
||||||
deleteAttachmentsParams.Set(":message_id", messageId);
|
deleteAttachmentsCmd.Set(":message_id", messageId);
|
||||||
deleteAttachmentsCmd.ExecuteNonQuery();
|
deleteAttachmentsCmd.ExecuteNonQuery();
|
||||||
|
|
||||||
deleteEmbedsParams.Set(":message_id", messageId);
|
deleteEmbedsCmd.Set(":message_id", messageId);
|
||||||
deleteEmbedsCmd.ExecuteNonQuery();
|
deleteEmbedsCmd.ExecuteNonQuery();
|
||||||
|
|
||||||
deleteReactionsParams.Set(":message_id", messageId);
|
deleteReactionsCmd.Set(":message_id", messageId);
|
||||||
deleteReactionsCmd.ExecuteNonQuery();
|
deleteReactionsCmd.ExecuteNonQuery();
|
||||||
|
|
||||||
if (!message.Attachments.IsEmpty) {
|
if (!message.Attachments.IsEmpty) {
|
||||||
foreach (var attachment in message.Attachments) {
|
foreach (var attachment in message.Attachments) {
|
||||||
attachmentParams.Set(":message_id", messageId);
|
attachmentCmd.Set(":message_id", messageId);
|
||||||
attachmentParams.Set(":attachment_id", attachment.Id);
|
attachmentCmd.Set(":attachment_id", attachment.Id);
|
||||||
attachmentParams.Set(":name", attachment.Name);
|
attachmentCmd.Set(":name", attachment.Name);
|
||||||
attachmentParams.Set(":type", attachment.Type);
|
attachmentCmd.Set(":type", attachment.Type);
|
||||||
attachmentParams.Set(":url", attachment.Url);
|
attachmentCmd.Set(":url", attachment.Url);
|
||||||
attachmentParams.Set(":size", attachment.Size);
|
attachmentCmd.Set(":size", attachment.Size);
|
||||||
attachmentCmd.ExecuteNonQuery();
|
attachmentCmd.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!message.Embeds.IsEmpty) {
|
if (!message.Embeds.IsEmpty) {
|
||||||
foreach (var embed in message.Embeds) {
|
foreach (var embed in message.Embeds) {
|
||||||
embedParams.Set(":message_id", messageId);
|
embedCmd.Set(":message_id", messageId);
|
||||||
embedParams.Set(":json", embed.Json);
|
embedCmd.Set(":json", embed.Json);
|
||||||
embedCmd.ExecuteNonQuery();
|
embedCmd.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!message.Reactions.IsEmpty) {
|
if (!message.Reactions.IsEmpty) {
|
||||||
foreach (var reaction in message.Reactions) {
|
foreach (var reaction in message.Reactions) {
|
||||||
reactionParams.Set(":message_id", messageId);
|
reactionCmd.Set(":message_id", messageId);
|
||||||
reactionParams.Set(":emoji_id", reaction.EmojiId);
|
reactionCmd.Set(":emoji_id", reaction.EmojiId);
|
||||||
reactionParams.Set(":emoji_name", reaction.EmojiName);
|
reactionCmd.Set(":emoji_name", reaction.EmojiName);
|
||||||
reactionParams.Set(":emoji_flags", (int) reaction.EmojiFlags);
|
reactionCmd.Set(":emoji_flags", (int) reaction.EmojiFlags);
|
||||||
reactionParams.Set(":count", reaction.Count);
|
reactionCmd.Set(":count", reaction.Count);
|
||||||
reactionCmd.ExecuteNonQuery();
|
reactionCmd.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,16 +268,16 @@ namespace DHT.Server.Database.Sqlite {
|
|||||||
using var reader = cmd.ExecuteReader();
|
using var reader = cmd.ExecuteReader();
|
||||||
|
|
||||||
while (reader.Read()) {
|
while (reader.Read()) {
|
||||||
ulong id = (ulong) reader.GetInt64(0);
|
ulong id = reader.GetUint64(0);
|
||||||
|
|
||||||
list.Add(new Message {
|
list.Add(new Message {
|
||||||
Id = id,
|
Id = id,
|
||||||
Sender = (ulong) reader.GetInt64(1),
|
Sender = reader.GetUint64(1),
|
||||||
Channel = (ulong) reader.GetInt64(2),
|
Channel = reader.GetUint64(2),
|
||||||
Text = reader.GetString(3),
|
Text = reader.GetString(3),
|
||||||
Timestamp = reader.GetInt64(4),
|
Timestamp = reader.GetInt64(4),
|
||||||
EditTimestamp = reader.IsDBNull(5) ? null : reader.GetInt64(5),
|
EditTimestamp = reader.IsDBNull(5) ? null : reader.GetInt64(5),
|
||||||
RepliedToId = reader.IsDBNull(6) ? null : (ulong) reader.GetInt64(6),
|
RepliedToId = reader.IsDBNull(6) ? null : reader.GetUint64(6),
|
||||||
Attachments = attachments.GetListOrNull(id)?.ToImmutableArray() ?? ImmutableArray<Attachment>.Empty,
|
Attachments = attachments.GetListOrNull(id)?.ToImmutableArray() ?? ImmutableArray<Attachment>.Empty,
|
||||||
Embeds = embeds.GetListOrNull(id)?.ToImmutableArray() ?? ImmutableArray<Embed>.Empty,
|
Embeds = embeds.GetListOrNull(id)?.ToImmutableArray() ?? ImmutableArray<Embed>.Empty,
|
||||||
Reactions = reactions.GetListOrNull(id)?.ToImmutableArray() ?? ImmutableArray<Reaction>.Empty
|
Reactions = reactions.GetListOrNull(id)?.ToImmutableArray() ?? ImmutableArray<Reaction>.Empty
|
||||||
@ -328,14 +312,14 @@ namespace DHT.Server.Database.Sqlite {
|
|||||||
using var reader = cmd.ExecuteReader();
|
using var reader = cmd.ExecuteReader();
|
||||||
|
|
||||||
while (reader.Read()) {
|
while (reader.Read()) {
|
||||||
ulong messageId = (ulong) reader.GetInt64(0);
|
ulong messageId = reader.GetUint64(0);
|
||||||
|
|
||||||
dict.Add(messageId, new Attachment {
|
dict.Add(messageId, new Attachment {
|
||||||
Id = (ulong) reader.GetInt64(1),
|
Id = reader.GetUint64(1),
|
||||||
Name = reader.GetString(2),
|
Name = reader.GetString(2),
|
||||||
Type = reader.IsDBNull(3) ? null : reader.GetString(3),
|
Type = reader.IsDBNull(3) ? null : reader.GetString(3),
|
||||||
Url = reader.GetString(4),
|
Url = reader.GetString(4),
|
||||||
Size = (ulong) reader.GetInt64(5)
|
Size = reader.GetUint64(5)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,7 +333,7 @@ namespace DHT.Server.Database.Sqlite {
|
|||||||
using var reader = cmd.ExecuteReader();
|
using var reader = cmd.ExecuteReader();
|
||||||
|
|
||||||
while (reader.Read()) {
|
while (reader.Read()) {
|
||||||
ulong messageId = (ulong) reader.GetInt64(0);
|
ulong messageId = reader.GetUint64(0);
|
||||||
|
|
||||||
dict.Add(messageId, new Embed {
|
dict.Add(messageId, new Embed {
|
||||||
Json = reader.GetString(1)
|
Json = reader.GetString(1)
|
||||||
@ -366,10 +350,10 @@ namespace DHT.Server.Database.Sqlite {
|
|||||||
using var reader = cmd.ExecuteReader();
|
using var reader = cmd.ExecuteReader();
|
||||||
|
|
||||||
while (reader.Read()) {
|
while (reader.Read()) {
|
||||||
ulong messageId = (ulong) reader.GetInt64(0);
|
ulong messageId = reader.GetUint64(0);
|
||||||
|
|
||||||
dict.Add(messageId, new Reaction {
|
dict.Add(messageId, new Reaction {
|
||||||
EmojiId = reader.IsDBNull(1) ? null : (ulong) reader.GetInt64(1),
|
EmojiId = reader.IsDBNull(1) ? null : reader.GetUint64(1),
|
||||||
EmojiName = reader.IsDBNull(2) ? null : reader.GetString(2),
|
EmojiName = reader.IsDBNull(2) ? null : reader.GetString(2),
|
||||||
EmojiFlags = (EmojiFlags) reader.GetInt16(3),
|
EmojiFlags = (EmojiFlags) reader.GetInt16(3),
|
||||||
Count = reader.GetInt32(4)
|
Count = reader.GetInt32(4)
|
||||||
@ -380,23 +364,19 @@ namespace DHT.Server.Database.Sqlite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateServerStatistics() {
|
private void UpdateServerStatistics() {
|
||||||
using var cmd = conn.Command("SELECT COUNT(*) FROM servers");
|
Statistics.TotalServers = conn.SelectScalar("SELECT COUNT(*) FROM servers") as long? ?? 0;
|
||||||
Statistics.TotalServers = cmd.ExecuteScalar() as long? ?? 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateChannelStatistics() {
|
private void UpdateChannelStatistics() {
|
||||||
using var cmd = conn.Command("SELECT COUNT(*) FROM channels");
|
Statistics.TotalChannels = conn.SelectScalar("SELECT COUNT(*) FROM channels") as long? ?? 0;
|
||||||
Statistics.TotalChannels = cmd.ExecuteScalar() as long? ?? 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateUserStatistics() {
|
private void UpdateUserStatistics() {
|
||||||
using var cmd = conn.Command("SELECT COUNT(*) FROM users");
|
Statistics.TotalUsers = conn.SelectScalar("SELECT COUNT(*) FROM users") as long? ?? 0;
|
||||||
Statistics.TotalUsers = cmd.ExecuteScalar() as long? ?? 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateMessageStatistics() {
|
private void UpdateMessageStatistics() {
|
||||||
using var cmd = conn.Command("SELECT COUNT(*) FROM messages");
|
Statistics.TotalMessages = conn.SelectScalar("SELECT COUNT(*) FROM messages") as long? ?? 0L;
|
||||||
Statistics.TotalMessages = cmd.ExecuteScalar() as long? ?? 0L;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,31 +10,54 @@ namespace DHT.Server.Database.Sqlite {
|
|||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SqliteCommand Insert(this SqliteConnection conn, string tableName, string[] columns) {
|
public static object? SelectScalar(this SqliteConnection conn, string sql) {
|
||||||
string columnNames = string.Join(',', columns);
|
using var cmd = conn.Command(sql);
|
||||||
string columnParams = string.Join(',', columns.Select(static c => ':' + c));
|
return cmd.ExecuteScalar();
|
||||||
|
|
||||||
return conn.Command("INSERT INTO " + tableName + " (" + columnNames + ")" +
|
|
||||||
"VALUES (" + columnParams + ")");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SqliteCommand Upsert(this SqliteConnection conn, string tableName, string[] columns) {
|
public static SqliteCommand Insert(this SqliteConnection conn, string tableName, (string Name, SqliteType Type)[] columns) {
|
||||||
string columnNames = string.Join(',', columns);
|
string columnNames = string.Join(',', columns.Select(static c => c.Name));
|
||||||
string columnParams = string.Join(',', columns.Select(static c => ':' + c));
|
string columnParams = string.Join(',', columns.Select(static c => ':' + c.Name));
|
||||||
string columnUpdates = string.Join(',', columns.Skip(1).Select(static c => c + " = excluded." + c));
|
|
||||||
|
|
||||||
return conn.Command("INSERT INTO " + tableName + " (" + columnNames + ")" +
|
var cmd = conn.Command("INSERT INTO " + tableName + " (" + columnNames + ")" +
|
||||||
"VALUES (" + columnParams + ")" +
|
"VALUES (" + columnParams + ")");
|
||||||
"ON CONFLICT (" + columns[0] + ")" +
|
|
||||||
"DO UPDATE SET " + columnUpdates);
|
CreateParameters(cmd, columns);
|
||||||
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddAndSet(this SqliteParameterCollection parameters, string key, object? value) {
|
public static SqliteCommand Upsert(this SqliteConnection conn, string tableName, (string Name, SqliteType Type)[] columns) {
|
||||||
parameters.AddWithValue(key, value ?? DBNull.Value);
|
string columnNames = string.Join(',', columns.Select(static c => c.Name));
|
||||||
|
string columnParams = string.Join(',', columns.Select(static c => ':' + c.Name));
|
||||||
|
string columnUpdates = string.Join(',', columns.Skip(1).Select(static c => c.Name + " = excluded." + c.Name));
|
||||||
|
|
||||||
|
var cmd = conn.Command("INSERT INTO " + tableName + " (" + columnNames + ")" +
|
||||||
|
"VALUES (" + columnParams + ")" +
|
||||||
|
"ON CONFLICT (" + columns[0].Name + ")" +
|
||||||
|
"DO UPDATE SET " + columnUpdates);
|
||||||
|
|
||||||
|
CreateParameters(cmd, columns);
|
||||||
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Set(this SqliteParameterCollection parameters, string key, object? value) {
|
public static SqliteCommand Delete(this SqliteConnection conn, string tableName, (string Name, SqliteType Type) column) {
|
||||||
parameters[key].Value = value ?? DBNull.Value;
|
var cmd = conn.Command("DELETE FROM " + tableName + " WHERE " + column.Name + " = :" + column.Name);
|
||||||
|
CreateParameters(cmd, new [] { column });
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateParameters(SqliteCommand cmd, (string Name, SqliteType Type)[] columns) {
|
||||||
|
foreach (var (name, type) in columns) {
|
||||||
|
cmd.Parameters.Add(":" + name, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Set(this SqliteCommand cmd, string key, object? value) {
|
||||||
|
cmd.Parameters[key].Value = value ?? DBNull.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ulong GetUint64(this SqliteDataReader reader, int ordinal) {
|
||||||
|
return (ulong) reader.GetInt64(ordinal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="5.0.5" />
|
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Utils\Utils.csproj" />
|
<ProjectReference Include="..\Utils\Utils.csproj" />
|
||||||
|
@ -1,8 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace DHT.Utils.Logging {
|
namespace DHT.Utils.Logging {
|
||||||
public sealed class Log {
|
public sealed class Log {
|
||||||
|
public static bool IsDebugEnabled { get; set; }
|
||||||
|
|
||||||
|
static Log() {
|
||||||
|
#if DEBUG
|
||||||
|
IsDebugEnabled = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
public static Log ForType<T>() {
|
public static Log ForType<T>() {
|
||||||
return ForType(typeof(T));
|
return ForType(typeof(T));
|
||||||
}
|
}
|
||||||
@ -11,19 +21,54 @@ namespace DHT.Utils.Logging {
|
|||||||
return new Log(type.Name);
|
return new Log(type.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly string tag;
|
public static Log ForType<T>(string context) {
|
||||||
|
return ForType(typeof(T), context);
|
||||||
|
}
|
||||||
|
|
||||||
private Log(string tag) {
|
public static Log ForType(Type type, string context) {
|
||||||
|
return new Log(type.Name, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly string tag;
|
||||||
|
private readonly string? context;
|
||||||
|
|
||||||
|
private Log(string tag, string? context = null) {
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FormatTags(StringBuilder builder) {
|
||||||
|
builder.Append('[').Append(tag).Append("] ");
|
||||||
|
|
||||||
|
if (context != null) {
|
||||||
|
builder.Append('[').Append(context).Append("] ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LogLevel(ConsoleColor color, string level, string text) {
|
private void LogLevel(ConsoleColor color, string level, string text) {
|
||||||
|
ConsoleColor prevColor = Console.ForegroundColor;
|
||||||
Console.ForegroundColor = color;
|
Console.ForegroundColor = color;
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
foreach (string line in text.Replace("\r", "").Split('\n')) {
|
foreach (string line in text.Replace("\r", "").Split('\n')) {
|
||||||
string formatted = $"[{level}] [{tag}] {line}";
|
builder.Clear();
|
||||||
|
builder.Append('[').Append(level).Append("] ");
|
||||||
|
FormatTags(builder);
|
||||||
|
builder.Append(line);
|
||||||
|
|
||||||
|
string formatted = builder.ToString();
|
||||||
Console.WriteLine(formatted);
|
Console.WriteLine(formatted);
|
||||||
Trace.WriteLine(formatted);
|
Trace.WriteLine(formatted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console.ForegroundColor = prevColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Debug(string message) {
|
||||||
|
if (IsDebugEnabled) {
|
||||||
|
LogLevel(ConsoleColor.Gray, "DEBUG", message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Info(string message) {
|
public void Info(string message) {
|
||||||
@ -41,5 +86,9 @@ namespace DHT.Utils.Logging {
|
|||||||
public void Error(Exception e) {
|
public void Error(Exception e) {
|
||||||
LogLevel(ConsoleColor.Red, "ERROR", e.ToString());
|
LogLevel(ConsoleColor.Red, "ERROR", e.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Perf Start([CallerMemberName] string callerMemberName = "") {
|
||||||
|
return Perf.Start(this, callerMemberName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
29
app/Utils/Logging/Perf.cs
Normal file
29
app/Utils/Logging/Perf.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace DHT.Utils.Logging {
|
||||||
|
public sealed class Perf {
|
||||||
|
internal static Perf Start(Log log, [CallerMemberName] string callerMemberName = "") {
|
||||||
|
return new Perf(log, callerMemberName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Log log;
|
||||||
|
private readonly string method;
|
||||||
|
private readonly Stopwatch stopwatch;
|
||||||
|
|
||||||
|
private Perf(Log log, string method) {
|
||||||
|
this.log = log;
|
||||||
|
this.method = method;
|
||||||
|
this.stopwatch = new Stopwatch();
|
||||||
|
this.stopwatch.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void End() {
|
||||||
|
stopwatch.Stop();
|
||||||
|
|
||||||
|
if (Log.IsDebugEnabled) {
|
||||||
|
log.Debug($"Finished '{method}' in {stopwatch.ElapsedMilliseconds} ms.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user