Compare commits

..

6 Commits

6 changed files with 25 additions and 29 deletions

View File

@ -9,7 +9,7 @@ using DHT.Utils.Tasks;
namespace DHT.Desktop.Main.Controls { namespace DHT.Desktop.Main.Controls {
sealed class AttachmentFilterPanelModel : BaseModel, IDisposable { sealed class AttachmentFilterPanelModel : BaseModel, IDisposable {
public sealed record Unit(string Name, int Scale); public sealed record Unit(string Name, uint Scale);
private static readonly Unit[] AllUnits = { private static readonly Unit[] AllUnits = {
new ("B", 1), new ("B", 1),
@ -26,7 +26,7 @@ namespace DHT.Desktop.Main.Controls {
public string FilterStatisticsText { get; private set; } = ""; public string FilterStatisticsText { get; private set; } = "";
private bool limitSize = false; private bool limitSize = false;
private int maximumSize = 0; private ulong maximumSize = 0L;
private Unit maximumSizeUnit = AllUnits[0]; private Unit maximumSizeUnit = AllUnits[0];
public bool LimitSize { public bool LimitSize {
@ -34,7 +34,7 @@ namespace DHT.Desktop.Main.Controls {
set => Change(ref limitSize, value); set => Change(ref limitSize, value);
} }
public int MaximumSize { public ulong MaximumSize {
get => maximumSize; get => maximumSize;
set => Change(ref maximumSize, value); set => Change(ref maximumSize, value);
} }
@ -116,7 +116,11 @@ namespace DHT.Desktop.Main.Controls {
AttachmentFilter filter = new(); AttachmentFilter filter = new();
if (LimitSize) { if (LimitSize) {
try {
filter.MaxBytes = maximumSize * maximumSizeUnit.Scale; filter.MaxBytes = maximumSize * maximumSizeUnit.Scale;
} catch (ArithmeticException) {
// set no size limit, because the overflown size is larger than any file could possibly be
}
} }
return filter; return filter;

View File

@ -169,7 +169,7 @@ namespace DHT.Desktop.Main.Controls {
var exportedMessageCountStr = exportedMessageCount?.Format() ?? "(...)"; var exportedMessageCountStr = exportedMessageCount?.Format() ?? "(...)";
var totalMessageCountStr = totalMessageCount?.Format() ?? "(...)"; var totalMessageCountStr = totalMessageCount?.Format() ?? "(...)";
FilterStatisticsText = verb + " " + exportedMessageCountStr + " out of " + totalMessageCountStr + " message" + (totalMessageCount is null or 0 ? "." : "s."); FilterStatisticsText = verb + " " + exportedMessageCountStr + " out of " + totalMessageCountStr + " message" + (totalMessageCount is null or 1 ? "." : "s.");
OnPropertyChanged(nameof(FilterStatisticsText)); OnPropertyChanged(nameof(FilterStatisticsText));
} }

View File

@ -175,7 +175,6 @@ namespace DHT.Desktop.Main.Pages {
}; };
db.RemoveDownloadItems(allExceptFailedFilter, FilterRemovalMode.KeepMatching); db.RemoveDownloadItems(allExceptFailedFilter, FilterRemovalMode.KeepMatching);
downloadStatisticsComputer.Recompute();
if (IsDownloading) { if (IsDownloading) {
EnqueueDownloadItems(); EnqueueDownloadItems();

View File

@ -1,7 +1,7 @@
const DISCORD = (function() { const DISCORD = (function() {
const regex = { const regex = {
formatBold: /\*\*([\s\S]+?)\*\*(?!\*)/g, formatBold: /\*\*([\s\S]+?)\*\*(?!\*)/g,
formatItalic: /(.)?\*([\s\S]+?)\*(?!\*)/g, formatItalic: /(.)?([_*])([\s\S]+?)\2(?!\2)/g,
formatUnderline: /__([\s\S]+?)__(?!_)/g, formatUnderline: /__([\s\S]+?)__(?!_)/g,
formatStrike: /~~([\s\S]+?)~~(?!~)/g, formatStrike: /~~([\s\S]+?)~~(?!~)/g,
formatCodeInline: /(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/g, formatCodeInline: /(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/g,
@ -9,7 +9,7 @@ const DISCORD = (function() {
formatUrl: /(\b(?:https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, formatUrl: /(\b(?:https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig,
formatUrlNoEmbed: /<(\b(?:https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])>/ig, formatUrlNoEmbed: /<(\b(?:https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])>/ig,
specialEscapedBacktick: /\\`/g, specialEscapedBacktick: /\\`/g,
specialEscapedSingle: /\\([*\\])/g, specialEscapedSingle: /\\([*_\\])/g,
specialEscapedDouble: /\\__|_\\_|\\_\\_|\\~~|~\\~|\\~\\~/g, specialEscapedDouble: /\\__|_\\_|\\_\\_|\\~~|~\\~|\\~\\~/g,
specialUnescaped: /([*_~\\])/g, specialUnescaped: /([*_~\\])/g,
mentionRole: /&lt;@&(\d+?)&gt;/g, mentionRole: /&lt;@&(\d+?)&gt;/g,
@ -47,8 +47,8 @@ const DISCORD = (function() {
.replace(regex.specialEscapedSingle, escapeHtmlMatch) .replace(regex.specialEscapedSingle, escapeHtmlMatch)
.replace(regex.specialEscapedDouble, full => full.replace(/\\/g, "").replace(/(.)/g, escapeHtmlMatch)) .replace(regex.specialEscapedDouble, full => full.replace(/\\/g, "").replace(/(.)/g, escapeHtmlMatch))
.replace(regex.formatBold, "<b>$1</b>") .replace(regex.formatBold, "<b>$1</b>")
.replace(regex.formatItalic, (full, pre, match) => pre === "\\" ? full : (pre || "") + "<i>" + match + "</i>")
.replace(regex.formatUnderline, "<u>$1</u>") .replace(regex.formatUnderline, "<u>$1</u>")
.replace(regex.formatItalic, (full, pre, char, match) => pre === "\\" ? full : (pre || "") + "<i>" + match + "</i>")
.replace(regex.formatStrike, "<s>$1</s>"); .replace(regex.formatStrike, "<s>$1</s>");
} }

View File

@ -1,6 +1,6 @@
namespace DHT.Server.Data.Filters { namespace DHT.Server.Data.Filters {
public sealed class AttachmentFilter { public sealed class AttachmentFilter {
public long? MaxBytes { get; set; } = null; public ulong? MaxBytes { get; set; } = null;
public DownloadItemRules? DownloadItemRule { get; set; } = null; public DownloadItemRules? DownloadItemRule { get; set; } = null;

View File

@ -403,21 +403,17 @@ LEFT JOIN replied_to rt ON m.message_id = rt.message_id" + filter.GenerateWhereC
} }
public void RemoveMessages(MessageFilter filter, FilterRemovalMode mode) { public void RemoveMessages(MessageFilter filter, FilterRemovalMode mode) {
var whereClause = filter.GenerateWhereClause(invert: mode == FilterRemovalMode.KeepMatching);
if (!string.IsNullOrEmpty(whereClause)) {
var perf = log.Start(); var perf = log.Start();
DeleteFromTable("messages", whereClause); DeleteFromTable("messages", filter.GenerateWhereClause(invert: mode == FilterRemovalMode.KeepMatching));
totalMessagesComputer.Recompute(); totalMessagesComputer.Recompute();
perf.End(); perf.End();
} }
}
public int CountAttachments(AttachmentFilter? filter = null) { public int CountAttachments(AttachmentFilter? filter = null) {
using var conn = pool.Take(); using var conn = pool.Take();
using var cmd = conn.Command("SELECT COUNT(*) FROM attachments a" + filter.GenerateWhereClause("a")); using var cmd = conn.Command("SELECT COUNT(DISTINCT url) FROM attachments a" + filter.GenerateWhereClause("a"));
using var reader = cmd.ExecuteReader(); using var reader = cmd.ExecuteReader();
return reader.Read() ? reader.GetInt32(0) : 0; return reader.Read() ? reader.GetInt32(0) : 0;
@ -476,7 +472,7 @@ LEFT JOIN replied_to rt ON m.message_id = rt.message_id" + filter.GenerateWhereC
public void EnqueueDownloadItems(AttachmentFilter? filter = null) { public void EnqueueDownloadItems(AttachmentFilter? filter = null) {
using var conn = pool.Take(); using var conn = pool.Take();
using var cmd = conn.Command("INSERT INTO downloads (url, status, size) SELECT a.url, :enqueued, a.size FROM attachments a" + filter.GenerateWhereClause("a")); using var cmd = conn.Command("INSERT INTO downloads (url, status, size) SELECT a.url, :enqueued, MAX(a.size) FROM attachments a" + filter.GenerateWhereClause("a") + " GROUP BY a.url");
cmd.AddAndSet(":enqueued", SqliteType.Integer, (int) DownloadStatus.Enqueued); cmd.AddAndSet(":enqueued", SqliteType.Integer, (int) DownloadStatus.Enqueued);
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
@ -502,16 +498,13 @@ LEFT JOIN replied_to rt ON m.message_id = rt.message_id" + filter.GenerateWhereC
} }
public void RemoveDownloadItems(DownloadItemFilter? filter, FilterRemovalMode mode) { public void RemoveDownloadItems(DownloadItemFilter? filter, FilterRemovalMode mode) {
var whereClause = filter.GenerateWhereClause(invert: mode == FilterRemovalMode.KeepMatching); DeleteFromTable("downloads", filter.GenerateWhereClause(invert: mode == FilterRemovalMode.KeepMatching));
totalDownloadsComputer.Recompute();
if (!string.IsNullOrEmpty(whereClause)) {
DeleteFromTable("downloads", whereClause);
}
} }
public DownloadStatusStatistics GetDownloadStatusStatistics() { public DownloadStatusStatistics GetDownloadStatusStatistics() {
static void LoadUndownloadedStatistics(ISqliteConnection conn, DownloadStatusStatistics result) { static void LoadUndownloadedStatistics(ISqliteConnection conn, DownloadStatusStatistics result) {
using var cmd = conn.Command("SELECT IFNULL(COUNT(filtered.size), 0), IFNULL(SUM(filtered.size), 0) FROM (SELECT DISTINCT a.url, a.size FROM attachments a WHERE a.url NOT IN (SELECT d.url FROM downloads d)) filtered"); using var cmd = conn.Command("SELECT IFNULL(COUNT(size), 0), IFNULL(SUM(size), 0) FROM (SELECT MAX(a.size) size FROM attachments a WHERE a.url NOT IN (SELECT d.url FROM downloads d) GROUP BY a.url)");
using var reader = cmd.ExecuteReader(); using var reader = cmd.ExecuteReader();
if (reader.Read()) { if (reader.Read()) {
@ -655,7 +648,7 @@ FROM downloads");
private long ComputeAttachmentStatistics() { private long ComputeAttachmentStatistics() {
using var conn = pool.Take(); using var conn = pool.Take();
return conn.SelectScalar("SELECT COUNT(*) FROM attachments") as long? ?? 0L; return conn.SelectScalar("SELECT COUNT(DISTINCT url) FROM attachments") as long? ?? 0L;
} }
private void UpdateAttachmentStatistics(long totalAttachments) { private void UpdateAttachmentStatistics(long totalAttachments) {