mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-08-08 04:48:44 +00:00
Prevent heart activity spam and fix photo grouping
This commit is contained in:
parent
4d2645b7c3
commit
41d2b5be7d
3 changed files with 274 additions and 2 deletions
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using LBPUnion.ProjectLighthouse.Database;
|
using LBPUnion.ProjectLighthouse.Database;
|
||||||
|
@ -205,6 +206,55 @@ public class ActivityEventHandlerTests
|
||||||
.FirstOrDefault(a => a.Type == EventType.HeartLevel && a.SlotId == 1));
|
.FirstOrDefault(a => a.Type == EventType.HeartLevel && a.SlotId == 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task HeartedLevel_InsertDuplicate_ShouldRemoveOldActivity()
|
||||||
|
{
|
||||||
|
ActivityEntityEventHandler eventHandler = new();
|
||||||
|
DatabaseContext database = await MockHelper.GetTestDatabase(new List<UserEntity>
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Username = "test",
|
||||||
|
UserId = 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
SlotEntity slot = new()
|
||||||
|
{
|
||||||
|
SlotId = 1,
|
||||||
|
CreatorId = 1,
|
||||||
|
};
|
||||||
|
database.Slots.Add(slot);
|
||||||
|
|
||||||
|
LevelActivityEntity levelActivity = new()
|
||||||
|
{
|
||||||
|
UserId = 1,
|
||||||
|
SlotId = 1,
|
||||||
|
Type = EventType.HeartLevel,
|
||||||
|
Timestamp = DateTime.MinValue,
|
||||||
|
};
|
||||||
|
|
||||||
|
database.Activities.Add(levelActivity);
|
||||||
|
|
||||||
|
await database.SaveChangesAsync();
|
||||||
|
|
||||||
|
HeartedLevelEntity heartedLevel = new()
|
||||||
|
{
|
||||||
|
HeartedLevelId = 1,
|
||||||
|
UserId = 1,
|
||||||
|
SlotId = 1,
|
||||||
|
Slot = slot,
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.NotNull(database.Activities.OfType<LevelActivityEntity>()
|
||||||
|
.FirstOrDefault(a => a.Type == EventType.HeartLevel && a.SlotId == 1 && a.Timestamp == DateTime.MinValue));
|
||||||
|
|
||||||
|
eventHandler.OnEntityInserted(database, heartedLevel);
|
||||||
|
|
||||||
|
Assert.NotNull(database.Activities.OfType<LevelActivityEntity>()
|
||||||
|
.FirstOrDefault(a => a.Type == EventType.HeartLevel && a.SlotId == 1 && a.Timestamp != DateTime.MinValue));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task HeartedProfile_Insert_ShouldCreateUserActivity()
|
public async Task HeartedProfile_Insert_ShouldCreateUserActivity()
|
||||||
{
|
{
|
||||||
|
@ -231,6 +281,46 @@ public class ActivityEventHandlerTests
|
||||||
.FirstOrDefault(a => a.Type == EventType.HeartUser && a.TargetUserId == 1));
|
.FirstOrDefault(a => a.Type == EventType.HeartUser && a.TargetUserId == 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task HeartedProfile_InsertDuplicate_ShouldRemoveOldActivity()
|
||||||
|
{
|
||||||
|
ActivityEntityEventHandler eventHandler = new();
|
||||||
|
DatabaseContext database = await MockHelper.GetTestDatabase(new List<UserEntity>
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Username = "test",
|
||||||
|
UserId = 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
UserActivityEntity userActivity = new()
|
||||||
|
{
|
||||||
|
UserId = 1,
|
||||||
|
TargetUserId = 1,
|
||||||
|
Type = EventType.HeartUser,
|
||||||
|
Timestamp = DateTime.MinValue,
|
||||||
|
};
|
||||||
|
|
||||||
|
database.Activities.Add(userActivity);
|
||||||
|
await database.SaveChangesAsync();
|
||||||
|
|
||||||
|
Assert.NotNull(database.Activities.OfType<UserActivityEntity>()
|
||||||
|
.FirstOrDefault(a => a.Type == EventType.HeartUser && a.TargetUserId == 1 && a.Timestamp == DateTime.MinValue));
|
||||||
|
|
||||||
|
HeartedProfileEntity heartedProfile = new()
|
||||||
|
{
|
||||||
|
HeartedProfileId = 1,
|
||||||
|
UserId = 1,
|
||||||
|
HeartedUserId = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
eventHandler.OnEntityInserted(database, heartedProfile);
|
||||||
|
|
||||||
|
Assert.NotNull(database.Activities.OfType<UserActivityEntity>()
|
||||||
|
.FirstOrDefault(a => a.Type == EventType.HeartUser && a.TargetUserId == 1 && a.Timestamp != DateTime.MinValue));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task HeartedPlaylist_Insert_ShouldCreatePlaylistActivity()
|
public async Task HeartedPlaylist_Insert_ShouldCreatePlaylistActivity()
|
||||||
{
|
{
|
||||||
|
@ -265,6 +355,54 @@ public class ActivityEventHandlerTests
|
||||||
.FirstOrDefault(a => a.Type == EventType.HeartPlaylist && a.PlaylistId == 1));
|
.FirstOrDefault(a => a.Type == EventType.HeartPlaylist && a.PlaylistId == 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task HeartedPlaylist_InsertDuplicate_ShouldCreatePlaylistActivity()
|
||||||
|
{
|
||||||
|
ActivityEntityEventHandler eventHandler = new();
|
||||||
|
DatabaseContext database = await MockHelper.GetTestDatabase(new List<UserEntity>
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Username = "test",
|
||||||
|
UserId = 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
PlaylistEntity playlist = new()
|
||||||
|
{
|
||||||
|
PlaylistId = 1,
|
||||||
|
CreatorId = 1,
|
||||||
|
};
|
||||||
|
database.Playlists.Add(playlist);
|
||||||
|
|
||||||
|
PlaylistActivityEntity playlistActivity = new()
|
||||||
|
{
|
||||||
|
UserId = 1,
|
||||||
|
PlaylistId = 1,
|
||||||
|
Type = EventType.HeartPlaylist,
|
||||||
|
Timestamp = DateTime.MinValue,
|
||||||
|
};
|
||||||
|
database.Activities.Add(playlistActivity);
|
||||||
|
|
||||||
|
await database.SaveChangesAsync();
|
||||||
|
|
||||||
|
HeartedPlaylistEntity heartedPlaylist = new()
|
||||||
|
{
|
||||||
|
HeartedPlaylistId = 1,
|
||||||
|
UserId = 1,
|
||||||
|
PlaylistId = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.NotNull(database.Activities.OfType<PlaylistActivityEntity>()
|
||||||
|
.FirstOrDefault(a =>
|
||||||
|
a.Type == EventType.HeartPlaylist && a.PlaylistId == 1 && a.Timestamp == DateTime.MinValue));
|
||||||
|
|
||||||
|
eventHandler.OnEntityInserted(database, heartedPlaylist);
|
||||||
|
|
||||||
|
Assert.NotNull(database.Activities.OfType<PlaylistActivityEntity>()
|
||||||
|
.FirstOrDefault(a => a.Type == EventType.HeartPlaylist && a.PlaylistId == 1 && a.Timestamp != DateTime.MinValue));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task VisitedLevel_Insert_ShouldCreateLevelActivity()
|
public async Task VisitedLevel_Insert_ShouldCreateLevelActivity()
|
||||||
{
|
{
|
||||||
|
@ -696,6 +834,52 @@ public class ActivityEventHandlerTests
|
||||||
.FirstOrDefault(a => a.Type == EventType.UnheartLevel && a.SlotId == 1));
|
.FirstOrDefault(a => a.Type == EventType.UnheartLevel && a.SlotId == 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task HeartedLevel_DeleteDuplicate_ShouldRemoveOldActivity()
|
||||||
|
{
|
||||||
|
ActivityEntityEventHandler eventHandler = new();
|
||||||
|
DatabaseContext database = await MockHelper.GetTestDatabase(new List<UserEntity>
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Username = "test",
|
||||||
|
UserId = 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
SlotEntity slot = new()
|
||||||
|
{
|
||||||
|
SlotId = 1,
|
||||||
|
CreatorId = 1,
|
||||||
|
};
|
||||||
|
database.Slots.Add(slot);
|
||||||
|
|
||||||
|
LevelActivityEntity levelActivity = new()
|
||||||
|
{
|
||||||
|
UserId = 1,
|
||||||
|
SlotId = 1,
|
||||||
|
Type = EventType.UnheartLevel,
|
||||||
|
Timestamp = DateTime.MinValue,
|
||||||
|
};
|
||||||
|
|
||||||
|
database.Activities.Add(levelActivity);
|
||||||
|
|
||||||
|
HeartedLevelEntity heartedLevel = new()
|
||||||
|
{
|
||||||
|
HeartedLevelId = 1,
|
||||||
|
UserId = 1,
|
||||||
|
SlotId = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
database.HeartedLevels.Add(heartedLevel);
|
||||||
|
await database.SaveChangesAsync();
|
||||||
|
|
||||||
|
eventHandler.OnEntityDeleted(database, heartedLevel);
|
||||||
|
|
||||||
|
Assert.NotNull(database.Activities.OfType<LevelActivityEntity>()
|
||||||
|
.FirstOrDefault(a => a.Type == EventType.UnheartLevel && a.SlotId == 1 && a.Timestamp != DateTime.MinValue));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task HeartedProfile_Delete_ShouldCreateLevelActivity()
|
public async Task HeartedProfile_Delete_ShouldCreateLevelActivity()
|
||||||
{
|
{
|
||||||
|
@ -731,5 +915,46 @@ public class ActivityEventHandlerTests
|
||||||
Assert.NotNull(database.Activities.OfType<UserActivityEntity>()
|
Assert.NotNull(database.Activities.OfType<UserActivityEntity>()
|
||||||
.FirstOrDefault(a => a.Type == EventType.UnheartUser && a.UserId == 1));
|
.FirstOrDefault(a => a.Type == EventType.UnheartUser && a.UserId == 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task HeartedProfile_DeleteDuplicate_ShouldCreateLevelActivity()
|
||||||
|
{
|
||||||
|
ActivityEntityEventHandler eventHandler = new();
|
||||||
|
DatabaseContext database = await MockHelper.GetTestDatabase(new List<UserEntity>
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Username = "test",
|
||||||
|
UserId = 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
UserActivityEntity userActivity = new()
|
||||||
|
{
|
||||||
|
UserId = 1,
|
||||||
|
TargetUserId = 1,
|
||||||
|
Type = EventType.UnheartUser,
|
||||||
|
Timestamp = DateTime.MinValue,
|
||||||
|
};
|
||||||
|
database.Activities.Add(userActivity);
|
||||||
|
|
||||||
|
HeartedProfileEntity heartedProfile = new()
|
||||||
|
{
|
||||||
|
HeartedProfileId = 1,
|
||||||
|
UserId = 1,
|
||||||
|
HeartedUserId = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
database.HeartedProfiles.Add(heartedProfile);
|
||||||
|
await database.SaveChangesAsync();
|
||||||
|
|
||||||
|
Assert.NotNull(database.Activities.OfType<UserActivityEntity>()
|
||||||
|
.FirstOrDefault(a => a.Type == EventType.UnheartUser && a.UserId == 1 && a.Timestamp == DateTime.MinValue));
|
||||||
|
|
||||||
|
eventHandler.OnEntityDeleted(database, heartedProfile);
|
||||||
|
|
||||||
|
Assert.NotNull(database.Activities.OfType<UserActivityEntity>()
|
||||||
|
.FirstOrDefault(a => a.Type == EventType.UnheartUser && a.UserId == 1 && a.Timestamp != DateTime.MinValue));
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
|
@ -118,7 +118,7 @@ public static class ActivityQueryExtensions
|
||||||
? ((UserActivityEntity)a).TargetUserId
|
? ((UserActivityEntity)a).TargetUserId
|
||||||
: a is CommentActivityEntity && ((CommentActivityEntity)a).Comment.Type == CommentType.Profile
|
: a is CommentActivityEntity && ((CommentActivityEntity)a).Comment.Type == CommentType.Profile
|
||||||
? ((CommentActivityEntity)a).Comment.TargetUserId
|
? ((CommentActivityEntity)a).Comment.TargetUserId
|
||||||
: a is PhotoActivityEntity && ((PhotoActivityEntity)a).Photo.SlotId != 0
|
: a is PhotoActivityEntity && ((PhotoActivityEntity)a).Photo.SlotId == 0
|
||||||
? ((PhotoActivityEntity)a).Photo.CreatorId
|
? ((PhotoActivityEntity)a).Photo.CreatorId
|
||||||
: 0,
|
: 0,
|
||||||
TargetPlaylistId = a is PlaylistActivityEntity || a is PlaylistWithSlotActivityEntity
|
TargetPlaylistId = a is PlaylistActivityEntity || a is PlaylistWithSlotActivityEntity
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
using LBPUnion.ProjectLighthouse.Database;
|
using LBPUnion.ProjectLighthouse.Database;
|
||||||
|
using LBPUnion.ProjectLighthouse.Extensions;
|
||||||
using LBPUnion.ProjectLighthouse.Logging;
|
using LBPUnion.ProjectLighthouse.Logging;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Entities.Activity;
|
using LBPUnion.ProjectLighthouse.Types.Entities.Activity;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Entities.Interaction;
|
using LBPUnion.ProjectLighthouse.Types.Entities.Interaction;
|
||||||
|
@ -144,12 +146,57 @@ public class ActivityEntityEventHandler : IEntityEventHandler
|
||||||
InsertActivity(database, activity);
|
InsertActivity(database, activity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void RemoveDuplicateEvents(DatabaseContext database, ActivityEntity activity)
|
||||||
|
{
|
||||||
|
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
|
||||||
|
switch (activity.Type)
|
||||||
|
{
|
||||||
|
case EventType.HeartLevel:
|
||||||
|
case EventType.UnheartLevel:
|
||||||
|
{
|
||||||
|
if (activity is not LevelActivityEntity levelActivity) break;
|
||||||
|
|
||||||
|
DeleteActivity(a => a.TargetSlotId == levelActivity.SlotId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EventType.HeartUser:
|
||||||
|
case EventType.UnheartUser:
|
||||||
|
{
|
||||||
|
if (activity is not UserActivityEntity userActivity) break;
|
||||||
|
|
||||||
|
DeleteActivity(a => a.TargetUserId == userActivity.TargetUserId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EventType.HeartPlaylist:
|
||||||
|
{
|
||||||
|
if (activity is not PlaylistActivityEntity playlistActivity) break;
|
||||||
|
|
||||||
|
DeleteActivity(a => a.TargetPlaylistId == playlistActivity.PlaylistId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
void DeleteActivity(Expression<Func<ActivityDto, bool>> predicate)
|
||||||
|
{
|
||||||
|
database.Activities.ToActivityDto()
|
||||||
|
.Where(a => a.Activity.UserId == activity.UserId)
|
||||||
|
.Where(a => a.Activity.Type == activity.Type)
|
||||||
|
.Where(predicate)
|
||||||
|
.Select(a => a.Activity)
|
||||||
|
.ExecuteDelete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void InsertActivity(DatabaseContext database, ActivityEntity? activity)
|
private static void InsertActivity(DatabaseContext database, ActivityEntity? activity)
|
||||||
{
|
{
|
||||||
if (activity == null) return;
|
if (activity == null) return;
|
||||||
|
|
||||||
Logger.Debug("Inserting activity: " + activity.GetType().Name, LogArea.Activity);
|
Logger.Debug("Inserting activity: " + activity.GetType().Name, LogArea.Activity);
|
||||||
|
|
||||||
|
RemoveDuplicateEvents(database, activity);
|
||||||
|
|
||||||
activity.Timestamp = DateTime.UtcNow;
|
activity.Timestamp = DateTime.UtcNow;
|
||||||
database.Activities.Add(activity);
|
database.Activities.Add(activity);
|
||||||
database.SaveChanges();
|
database.SaveChanges();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue