diff --git a/app/.idea/.idea.DiscordHistoryTracker/.idea/avalonia.xml b/app/.idea/.idea.DiscordHistoryTracker/.idea/avalonia.xml
index e1c959d..e2bd7e1 100644
--- a/app/.idea/.idea.DiscordHistoryTracker/.idea/avalonia.xml
+++ b/app/.idea/.idea.DiscordHistoryTracker/.idea/avalonia.xml
@@ -8,6 +8,7 @@
+
diff --git a/app/Desktop/Main/Controls/FilterPanel.axaml b/app/Desktop/Main/Controls/FilterPanel.axaml
new file mode 100644
index 0000000..a39659c
--- /dev/null
+++ b/app/Desktop/Main/Controls/FilterPanel.axaml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filter by Date
+
+
+
+
+
+
+
+
+ Filter by Channel
+
+
+
+
+ Filter by User
+
+
+
+
+
+
diff --git a/app/Desktop/Main/Controls/FilterPanel.axaml.cs b/app/Desktop/Main/Controls/FilterPanel.axaml.cs
new file mode 100644
index 0000000..2d0aba6
--- /dev/null
+++ b/app/Desktop/Main/Controls/FilterPanel.axaml.cs
@@ -0,0 +1,21 @@
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace DHT.Desktop.Main.Controls {
+ public class FilterPanel : UserControl {
+ public FilterPanel() {
+ InitializeComponent();
+ }
+
+ private void InitializeComponent() {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public void CalendarDatePicker_OnSelectedDateChanged(object? sender, SelectionChangedEventArgs e) {
+ if (DataContext is FilterPanelModel model) {
+ model.StartDate = this.FindControl("StartDatePicker").SelectedDate;
+ model.EndDate = this.FindControl("EndDatePicker").SelectedDate;
+ }
+ }
+ }
+}
diff --git a/app/Desktop/Main/Controls/FilterPanelModel.cs b/app/Desktop/Main/Controls/FilterPanelModel.cs
new file mode 100644
index 0000000..eae84ed
--- /dev/null
+++ b/app/Desktop/Main/Controls/FilterPanelModel.cs
@@ -0,0 +1,234 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using DHT.Desktop.Dialogs;
+using DHT.Desktop.Models;
+using DHT.Server.Data;
+using DHT.Server.Data.Filters;
+using DHT.Server.Database;
+
+namespace DHT.Desktop.Main.Controls {
+ public class FilterPanelModel : BaseModel {
+ private static readonly HashSet FilterProperties = new () {
+ nameof(FilterByDate),
+ nameof(StartDate),
+ nameof(EndDate),
+ nameof(FilterByChannel),
+ nameof(IncludedChannels),
+ nameof(FilterByUser),
+ nameof(IncludedUsers)
+ };
+
+ public event PropertyChangedEventHandler? FilterPropertyChanged;
+
+ private bool filterByDate = false;
+ private DateTime? startDate = null;
+ private DateTime? endDate = null;
+ private bool filterByChannel = false;
+ private HashSet? includedChannels = null;
+ private bool filterByUser = false;
+ private HashSet? includedUsers = null;
+
+ public bool FilterByDate {
+ get => filterByDate;
+ set => Change(ref filterByDate, value);
+ }
+
+ public DateTime? StartDate {
+ get => startDate;
+ set => Change(ref startDate, value);
+ }
+
+ public DateTime? EndDate {
+ get => endDate;
+ set => Change(ref endDate, value);
+ }
+
+ public bool FilterByChannel {
+ get => filterByChannel;
+ set => Change(ref filterByChannel, value);
+ }
+
+ public HashSet IncludedChannels {
+ get => includedChannels ?? db.GetAllChannels().Select(channel => channel.Id).ToHashSet();
+ set => Change(ref includedChannels, value);
+ }
+
+ public bool FilterByUser {
+ get => filterByUser;
+ set => Change(ref filterByUser, value);
+ }
+
+
+ public HashSet IncludedUsers {
+ get => includedUsers ?? db.GetAllUsers().Select(user => user.Id).ToHashSet();
+ set => Change(ref includedUsers, value);
+ }
+
+ private string channelFilterLabel = "";
+
+ public string ChannelFilterLabel {
+ get => channelFilterLabel;
+ set => Change(ref channelFilterLabel, value);
+ }
+
+ private string userFilterLabel = "";
+
+ public string UserFilterLabel {
+ get => userFilterLabel;
+ set => Change(ref userFilterLabel, value);
+ }
+
+ private readonly Window window;
+ private readonly IDatabaseFile db;
+
+ [Obsolete("Designer")]
+ public FilterPanelModel() : this(null!, DummyDatabaseFile.Instance) {}
+
+ public FilterPanelModel(Window window, IDatabaseFile db) {
+ this.window = window;
+ this.db = db;
+
+ UpdateChannelFilterLabel();
+ UpdateUserFilterLabel();
+
+ PropertyChanged += OnPropertyChanged;
+ db.Statistics.PropertyChanged += OnDbStatisticsChanged;
+ }
+
+ private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e) {
+ if (e.PropertyName != null && FilterProperties.Contains(e.PropertyName)) {
+ FilterPropertyChanged?.Invoke(sender, e);
+ }
+
+ if (e.PropertyName is nameof(FilterByChannel) or nameof(IncludedChannels)) {
+ UpdateChannelFilterLabel();
+ }
+ else if (e.PropertyName is nameof(FilterByUser) or nameof(IncludedUsers)) {
+ UpdateUserFilterLabel();
+ }
+ }
+
+ private void OnDbStatisticsChanged(object? sender, PropertyChangedEventArgs e) {
+ if (e.PropertyName == nameof(DatabaseStatistics.TotalChannels)) {
+ UpdateChannelFilterLabel();
+ }
+ else if (e.PropertyName == nameof(DatabaseStatistics.TotalUsers)) {
+ UpdateUserFilterLabel();
+ }
+ }
+
+ public async void OpenChannelFilterDialog() {
+ var servers = db.GetAllServers().ToDictionary(server => server.Id);
+ var items = new List>();
+ var included = IncludedChannels;
+
+ foreach (var channel in db.GetAllChannels()) {
+ var channelId = channel.Id;
+ var channelName = channel.Name;
+
+ string title;
+ if (servers.TryGetValue(channel.Server, out var server)) {
+ var titleBuilder = new StringBuilder();
+ var serverType = server.Type;
+
+ titleBuilder.Append('[')
+ .Append(ServerTypes.ToString(serverType))
+ .Append("] ");
+
+ if (serverType == ServerType.DirectMessage) {
+ titleBuilder.Append(channelName);
+ }
+ else {
+ titleBuilder.Append(server.Name)
+ .Append(" - ")
+ .Append(channelName);
+ }
+
+ title = titleBuilder.ToString();
+ }
+ else {
+ title = channelName;
+ }
+
+ items.Add(new CheckBoxItem(channelId) {
+ Title = title,
+ Checked = included.Contains(channelId)
+ });
+ }
+
+ var result = await OpenIdFilterDialog(window, "Included Channels", items);
+ if (result != null) {
+ IncludedChannels = result;
+ }
+ }
+
+ public async void OpenUserFilterDialog() {
+ var items = new List>();
+ var included = IncludedUsers;
+
+ foreach (var user in db.GetAllUsers()) {
+ var name = user.Name;
+ var discriminator = user.Discriminator;
+
+ items.Add(new CheckBoxItem(user.Id) {
+ Title = discriminator == null ? name : name + " #" + discriminator,
+ Checked = included.Contains(user.Id)
+ });
+ }
+
+ var result = await OpenIdFilterDialog(window, "Included Users", items);
+ if (result != null) {
+ IncludedUsers = result;
+ }
+ }
+
+ private void UpdateChannelFilterLabel() {
+ long total = db.Statistics.TotalChannels;
+ long included = FilterByChannel ? IncludedChannels.Count : total;
+ ChannelFilterLabel = "Selected " + included + " / " + total + (total == 1 ? " channel." : " channels.");
+ }
+
+ private void UpdateUserFilterLabel() {
+ long total = db.Statistics.TotalUsers;
+ long included = FilterByUser ? IncludedUsers.Count : total;
+ UserFilterLabel = "Selected " + included + " / " + total + (total == 1 ? " user." : " users.");
+ }
+
+ public MessageFilter CreateFilter() {
+ MessageFilter filter = new();
+
+ if (FilterByDate) {
+ filter.StartDate = StartDate;
+ filter.EndDate = EndDate;
+ }
+
+ if (FilterByChannel) {
+ filter.ChannelIds = new HashSet(IncludedChannels);
+ }
+
+ if (FilterByUser) {
+ filter.UserIds = new HashSet(IncludedUsers);
+ }
+
+ return filter;
+ }
+
+ private static async Task?> OpenIdFilterDialog(Window window, string title, List> items) {
+ items.Sort((item1, item2) => item1.Title.CompareTo(item2.Title));
+
+ var model = new CheckBoxDialogModel(items) {
+ Title = title
+ };
+
+ var dialog = new CheckBoxDialog { DataContext = model };
+ var result = await dialog.ShowDialog(window);
+
+ return result == DialogResult.OkCancel.Ok ? model.SelectedItems.Select(item => item.Item).ToHashSet() : null;
+ }
+ }
+}
diff --git a/app/Desktop/Main/Pages/ViewerPage.axaml b/app/Desktop/Main/Pages/ViewerPage.axaml
index b5d7c54..95c6be3 100644
--- a/app/Desktop/Main/Pages/ViewerPage.axaml
+++ b/app/Desktop/Main/Pages/ViewerPage.axaml
@@ -3,6 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pages="clr-namespace:DHT.Desktop.Main.Pages"
+ xmlns:controls="clr-namespace:DHT.Desktop.Main.Controls"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="DHT.Desktop.Main.Pages.ViewerPage">
@@ -10,36 +11,13 @@
-
-
-
-
-
-
+
-
-
- Filter by Date
-
-
-
-
-
-
-
+
+
diff --git a/app/Desktop/Main/Pages/ViewerPage.axaml.cs b/app/Desktop/Main/Pages/ViewerPage.axaml.cs
index ba937f7..b00c763 100644
--- a/app/Desktop/Main/Pages/ViewerPage.axaml.cs
+++ b/app/Desktop/Main/Pages/ViewerPage.axaml.cs
@@ -10,12 +10,5 @@ namespace DHT.Desktop.Main.Pages {
private void InitializeComponent() {
AvaloniaXamlLoader.Load(this);
}
-
- public void CalendarDatePicker_OnSelectedDateChanged(object? sender, SelectionChangedEventArgs e) {
- if (DataContext is ViewerPageModel model) {
- model.StartDate = this.FindControl("StartDatePicker").SelectedDate;
- model.EndDate = this.FindControl("EndDatePicker").SelectedDate;
- }
- }
}
}
diff --git a/app/Desktop/Main/Pages/ViewerPageModel.cs b/app/Desktop/Main/Pages/ViewerPageModel.cs
index 8f373ca..bef8257 100644
--- a/app/Desktop/Main/Pages/ViewerPageModel.cs
+++ b/app/Desktop/Main/Pages/ViewerPageModel.cs
@@ -6,9 +6,9 @@ using System.IO;
using System.Threading.Tasks;
using System.Web;
using Avalonia.Controls;
+using DHT.Desktop.Main.Controls;
using DHT.Desktop.Models;
using DHT.Desktop.Resources;
-using DHT.Server.Data.Filters;
using DHT.Server.Database;
using DHT.Server.Database.Export;
@@ -16,26 +16,7 @@ namespace DHT.Desktop.Main.Pages {
public class ViewerPageModel : BaseModel {
public string ExportedMessageText { get; private set; } = "";
- private bool filterByDate = false;
-
- public bool FilterByDate {
- get => filterByDate;
- set => Change(ref filterByDate, value);
- }
-
- private DateTime? startDate = null;
-
- public DateTime? StartDate {
- get => startDate;
- set => Change(ref startDate, value);
- }
-
- private DateTime? endDate = null;
-
- public DateTime? EndDate {
- get => endDate;
- set => Change(ref endDate, value);
- }
+ private FilterPanelModel FilterModel { get; }
private readonly Window window;
private readonly IDatabaseFile db;
@@ -47,15 +28,14 @@ namespace DHT.Desktop.Main.Pages {
this.window = window;
this.db = db;
- this.PropertyChanged += OnPropertyChanged;
+ this.FilterModel = new FilterPanelModel(window, db);
+ this.FilterModel.FilterPropertyChanged += OnFilterPropertyChanged;
this.db.Statistics.PropertyChanged += OnDbStatisticsChanged;
UpdateStatistics();
}
- private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e) {
- if (e.PropertyName is nameof(FilterByDate) or nameof(StartDate) or nameof(EndDate)) {
- UpdateStatistics();
- }
+ private void OnFilterPropertyChanged(object? sender, PropertyChangedEventArgs e) {
+ UpdateStatistics();
}
private void OnDbStatisticsChanged(object? sender, PropertyChangedEventArgs e) {
@@ -64,24 +44,13 @@ namespace DHT.Desktop.Main.Pages {
}
}
- private MessageFilter CreateFilter() {
- MessageFilter filter = new();
-
- if (FilterByDate) {
- filter.StartDate = StartDate;
- filter.EndDate = EndDate;
- }
-
- return filter;
- }
-
private void UpdateStatistics() {
- ExportedMessageText = "Will export " + db.CountMessages(CreateFilter()) + " out of " + db.Statistics.TotalMessages + " message(s).";
+ ExportedMessageText = "Will export " + db.CountMessages(FilterModel.CreateFilter()) + " out of " + db.Statistics.TotalMessages + " message(s).";
OnPropertyChanged(nameof(ExportedMessageText));
}
private async Task GenerateViewerContents() {
- string json = ViewerJsonExport.Generate(db, CreateFilter());
+ string json = ViewerJsonExport.Generate(db, FilterModel.CreateFilter());
string index = await ResourceLoader.ReadTextAsync("Viewer/index.html");
string viewer = index.Replace("/*[JS]*/", await ResourceLoader.ReadJoinedAsync("Viewer/scripts/", '\n'))
diff --git a/app/Server/Data/Filters/MessageFilter.cs b/app/Server/Data/Filters/MessageFilter.cs
index d86361c..a14286b 100644
--- a/app/Server/Data/Filters/MessageFilter.cs
+++ b/app/Server/Data/Filters/MessageFilter.cs
@@ -6,6 +6,8 @@ namespace DHT.Server.Data.Filters {
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
- public HashSet MessageIds { get; } = new();
+ public HashSet? ChannelIds { get; set; } = null;
+ public HashSet? UserIds { get; set; } = null;
+ public HashSet? MessageIds { get; set; } = null;
}
}
diff --git a/app/Server/Database/DatabaseStatistics.cs b/app/Server/Database/DatabaseStatistics.cs
index 5027e92..3b43a88 100644
--- a/app/Server/Database/DatabaseStatistics.cs
+++ b/app/Server/Database/DatabaseStatistics.cs
@@ -5,6 +5,7 @@ namespace DHT.Server.Database {
public class DatabaseStatistics : INotifyPropertyChanged {
private long totalServers;
private long totalChannels;
+ private long totalUsers;
private long totalMessages;
public long TotalServers {
@@ -17,6 +18,11 @@ namespace DHT.Server.Database {
internal set => Change(out totalChannels, value);
}
+ public long TotalUsers {
+ get => totalUsers;
+ internal set => Change(out totalUsers, value);
+ }
+
public long TotalMessages {
get => totalMessages;
internal set => Change(out totalMessages, value);
@@ -33,6 +39,7 @@ namespace DHT.Server.Database {
return new DatabaseStatistics {
totalServers = totalServers,
totalChannels = totalChannels,
+ totalUsers = TotalUsers,
totalMessages = totalMessages
};
}
diff --git a/app/Server/Database/Export/ViewerJsonExport.cs b/app/Server/Database/Export/ViewerJsonExport.cs
index 3ca6a29..9e1dd89 100644
--- a/app/Server/Database/Export/ViewerJsonExport.cs
+++ b/app/Server/Database/Export/ViewerJsonExport.cs
@@ -8,26 +8,48 @@ using DHT.Server.Data.Filters;
namespace DHT.Server.Database.Export {
public static class ViewerJsonExport {
public static string Generate(IDatabaseFile db, MessageFilter? filter = null) {
- JsonSerializerOptions opts = new();
+ var includedUserIds = new HashSet();
+ var includedChannelIds = new HashSet();
+ var includedServerIds = new HashSet();
+
+ var includedMessages = db.GetMessages(filter);
+ var includedChannels = new List();
+
+ foreach (var message in includedMessages) {
+ includedUserIds.Add(message.Sender);
+ includedChannelIds.Add(message.Channel);
+ }
+
+ foreach (var channel in db.GetAllChannels()) {
+ if (includedChannelIds.Contains(channel.Id)) {
+ includedChannels.Add(channel);
+ includedServerIds.Add(channel.Server);
+ }
+ }
+
+ var opts = new JsonSerializerOptions();
opts.Converters.Add(new ViewerJsonSnowflakeSerializer());
- var users = GenerateUserList(db, out var userindex, out var userIndices);
- var servers = GenerateServerList(db, out var serverindex);
- var channels = GenerateChannelList(db, serverindex);
+ var users = GenerateUserList(db, includedUserIds, out var userindex, out var userIndices);
+ var servers = GenerateServerList(db, includedServerIds, out var serverindex);
+ var channels = GenerateChannelList(includedChannels, serverindex);
return JsonSerializer.Serialize(new {
meta = new { users, userindex, servers, channels },
- data = GenerateMessageList(db, filter, userIndices)
+ data = GenerateMessageList(includedMessages, userIndices)
}, opts);
}
- private static dynamic GenerateUserList(IDatabaseFile db, out List userindex, out Dictionary userIndices) {
+ private static dynamic GenerateUserList(IDatabaseFile db, HashSet userIds, out List userindex, out Dictionary userIndices) {
var users = new Dictionary();
userindex = new List();
userIndices = new Dictionary();
foreach (var user in db.GetAllUsers()) {
- var id = user.Id.ToString();
+ var id = user.Id;
+ if (!userIds.Contains(id)) {
+ continue;
+ }
dynamic obj = new ExpandoObject();
obj.name = user.Name;
@@ -40,20 +62,26 @@ namespace DHT.Server.Database.Export {
obj.tag = user.Discriminator;
}
- userIndices[user.Id] = users.Count;
- userindex.Add(id);
- users[id] = obj;
+ var idStr = id.ToString();
+ userIndices[id] = users.Count;
+ userindex.Add(idStr);
+ users[idStr] = obj;
}
return users;
}
- private static dynamic GenerateServerList(IDatabaseFile db, out Dictionary serverIndices) {
+ private static dynamic GenerateServerList(IDatabaseFile db, HashSet serverIds, out Dictionary serverIndices) {
var servers = new List();
serverIndices = new Dictionary();
foreach (var server in db.GetAllServers()) {
- serverIndices[server.Id] = servers.Count;
+ var id = server.Id;
+ if (!serverIds.Contains(id)) {
+ continue;
+ }
+
+ serverIndices[id] = servers.Count;
servers.Add(new {
name = server.Name,
type = ServerTypes.ToJsonViewerString(server.Type)
@@ -63,10 +91,10 @@ namespace DHT.Server.Database.Export {
return servers;
}
- private static dynamic GenerateChannelList(IDatabaseFile db, Dictionary serverIndices) {
+ private static dynamic GenerateChannelList(List includedChannels, Dictionary serverIndices) {
var channels = new Dictionary();
- foreach (var channel in db.GetAllChannels()) {
+ foreach (var channel in includedChannels) {
dynamic obj = new ExpandoObject();
obj.server = serverIndices[channel.Server];
obj.name = channel.Name;
@@ -93,10 +121,10 @@ namespace DHT.Server.Database.Export {
return channels;
}
- private static dynamic GenerateMessageList(IDatabaseFile db, MessageFilter? filter, Dictionary userIndices) {
+ private static dynamic GenerateMessageList(List includedMessages, Dictionary userIndices) {
var data = new Dictionary>();
- foreach (var grouping in db.GetMessages(filter).GroupBy(message => message.Channel)) {
+ foreach (var grouping in includedMessages.GroupBy(message => message.Channel)) {
var channel = grouping.Key.ToString();
var channelData = new Dictionary();
diff --git a/app/Server/Database/Sqlite/SqliteDatabaseFile.cs b/app/Server/Database/Sqlite/SqliteDatabaseFile.cs
index 7db1c9f..c324fb6 100644
--- a/app/Server/Database/Sqlite/SqliteDatabaseFile.cs
+++ b/app/Server/Database/Sqlite/SqliteDatabaseFile.cs
@@ -32,6 +32,7 @@ namespace DHT.Server.Database.Sqlite {
this.Statistics = new DatabaseStatistics();
UpdateServerStatistics();
UpdateChannelStatistics();
+ UpdateUserStatistics();
UpdateMessageStatistics();
}
@@ -129,6 +130,7 @@ namespace DHT.Server.Database.Sqlite {
}
tx.Commit();
+ UpdateUserStatistics();
}
public List GetAllUsers() {
@@ -369,6 +371,11 @@ namespace DHT.Server.Database.Sqlite {
Statistics.TotalChannels = cmd.ExecuteScalar() as long? ?? 0;
}
+ private void UpdateUserStatistics() {
+ using var cmd = conn.Command("SELECT COUNT(*) FROM users");
+ Statistics.TotalUsers = cmd.ExecuteScalar() as long? ?? 0;
+ }
+
private void UpdateMessageStatistics() {
using var cmd = conn.Command("SELECT COUNT(*) FROM messages");
Statistics.TotalMessages = cmd.ExecuteScalar() as long? ?? 0L;
diff --git a/app/Server/Database/Sqlite/SqliteMessageFilter.cs b/app/Server/Database/Sqlite/SqliteMessageFilter.cs
index fc89522..6489ee7 100644
--- a/app/Server/Database/Sqlite/SqliteMessageFilter.cs
+++ b/app/Server/Database/Sqlite/SqliteMessageFilter.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using DHT.Server.Data.Filters;
namespace DHT.Server.Database.Sqlite {
@@ -20,8 +19,16 @@ namespace DHT.Server.Database.Sqlite {
conditions.Add("timestamp <= " + new DateTimeOffset(filter.EndDate.Value).ToUnixTimeMilliseconds());
}
- if (filter.MessageIds.Count > 0) {
- conditions.Add("(" + string.Join(" OR ", filter.MessageIds.Select(id => "message_id = " + id)) + ")");
+ if (filter.ChannelIds != null) {
+ conditions.Add("channel_id IN (" + string.Join(",", filter.ChannelIds) + ")");
+ }
+
+ if (filter.UserIds != null) {
+ conditions.Add("sender_id IN (" + string.Join(",", filter.UserIds) + ")");
+ }
+
+ if (filter.MessageIds != null) {
+ conditions.Add("message_id IN (" + string.Join(",", filter.MessageIds) + ")");
}
return conditions.Count == 0 ? "" : " WHERE " + string.Join(" AND ", conditions);
diff --git a/app/Server/Endpoints/TrackMessagesEndpoint.cs b/app/Server/Endpoints/TrackMessagesEndpoint.cs
index 7748808..b113e5a 100644
--- a/app/Server/Endpoints/TrackMessagesEndpoint.cs
+++ b/app/Server/Endpoints/TrackMessagesEndpoint.cs
@@ -22,17 +22,19 @@ namespace DHT.Server.Endpoints {
throw new HttpException(HttpStatusCode.BadRequest, "Expected root element to be an array.");
}
- var addedMessageIdFilter = new MessageFilter();
+ var addedMessageIds = new HashSet();
var messages = new Message[root.GetArrayLength()];
int i = 0;
foreach (JsonElement ele in root.EnumerateArray()) {
var message = ReadMessage(ele, "message");
messages[i++] = message;
- addedMessageIdFilter.MessageIds.Add(message.Id);
+ addedMessageIds.Add(message.Id);
}
- bool anyNewMessages = Db.CountMessages(addedMessageIdFilter) < messages.Length;
+ var addedMessageFilter = new MessageFilter { MessageIds = addedMessageIds };
+ bool anyNewMessages = Db.CountMessages(addedMessageFilter) < messages.Length;
+
Db.AddMessages(messages);
return (HttpStatusCode.OK, anyNewMessages ? 1 : 0);