Skip to content

Commit dc17b04

Browse files
authored
Add option to filter out reuploaded levels (#792)
Closes #444.
2 parents 81dc578 + bfade0f commit dc17b04

10 files changed

Lines changed: 68 additions & 13 deletions

File tree

Refresh.Core/Services/CommandService.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,14 @@ namespace Refresh.Core.Services;
1414

1515
public class CommandService : EndpointService
1616
{
17-
private readonly MatchService _match;
1817
private readonly PlayNowService _levelListService;
1918

20-
public CommandService(Logger logger, MatchService match, PlayNowService levelListService) : base(logger) {
21-
this._match = match;
19+
public CommandService(Logger logger, PlayNowService levelListService) : base(logger)
20+
{
2221
this._levelListService = levelListService;
2322
}
2423

25-
private readonly HashSet<ObjectId> _usersPublishing = new();
24+
private readonly HashSet<ObjectId> _usersPublishing = [];
2625

2726
/// <summary>
2827
/// Start tracking the user, eg. they started publishing
@@ -125,6 +124,18 @@ public void HandleCommand(CommandInvocation command, GameDatabaseContext databas
125124
database.SetShowModdedContent(user, false);
126125
break;
127126
}
127+
case "showreupload":
128+
case "showreuploads":
129+
{
130+
database.SetShowReuploadedContent(user, true);
131+
break;
132+
}
133+
case "hidereupload":
134+
case "hidereuploads":
135+
{
136+
database.SetShowReuploadedContent(user, false);
137+
break;
138+
}
128139
case "play":
129140
{
130141
if (CommonPatterns.Sha1Regex().IsMatch(command.Arguments))

Refresh.Database/Extensions/LevelEnumerableExtensions.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ public static IQueryable<GameLevel> FilterByLevelFilterSettings(this IQueryable<
4141
// If the user has it disabled globally and the filter doesnt enable it, or the filter disables it, disable modded content from being shown
4242
if ((user is { ShowModdedContent: false } && levelFilterSettings.ShowModdedLevels != true) || levelFilterSettings.ShowModdedLevels == false)
4343
levels = levels.Where(l => !l.IsModded);
44+
45+
if ((user is { ShowReuploadedContent: false } && levelFilterSettings.ShowReuploadedLevels != true) || levelFilterSettings.ShowReuploadedLevels == false)
46+
levels = levels.Where(l => !l.IsReUpload);
4447

4548
// Don't allow beta builds to use this filtering option
4649
// If the client specifies this option then it will filter out *all* levels.
@@ -89,6 +92,9 @@ public static IEnumerable<GameLevel> FilterByLevelFilterSettings(this IEnumerabl
8992
if ((user is { ShowModdedContent: false } && levelFilterSettings.ShowModdedLevels != true) || levelFilterSettings.ShowModdedLevels == false)
9093
levels = levels.Where(l => !l.IsModded);
9194

95+
if ((user is { ShowReuploadedContent: false } && levelFilterSettings.ShowReuploadedLevels != true) || levelFilterSettings.ShowReuploadedLevels == false)
96+
levels = levels.Where(l => !l.IsReUpload);
97+
9298
// Don't allow beta builds to use this filtering option
9399
// If the client specifies this option then it will filter out *all* levels.
94100
if (levelFilterSettings.GameVersion != TokenGame.BetaBuild)
@@ -122,7 +128,7 @@ public static IEnumerable<GameLevel> FilterByLevelFilterSettings(this IEnumerabl
122128
// };
123129

124130
// Filter out sub levels that weren't published by self
125-
levels = levels.Where(l => !l.IsSubLevel || l.Publisher?.UserId == user?.UserId);
131+
levels = levels.Where(l => !l.IsSubLevel || l.Publisher == user);
126132

127133
return levels;
128134
}

Refresh.Database/GameDatabaseContext.Users.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ public void UpdateUserData(GameUser user, IApiEditUserRequest data)
204204

205205
if (data.ShowModdedContent != null)
206206
user.ShowModdedContent = data.ShowModdedContent.Value;
207+
208+
if (data.ShowReuploadedContent != null)
209+
user.ShowReuploadedContent = data.ShowReuploadedContent.Value;
207210
});
208211
}
209212

@@ -380,6 +383,14 @@ public void SetShowModdedContent(GameUser user, bool value)
380383
user.ShowModdedContent = value;
381384
});
382385
}
386+
387+
public void SetShowReuploadedContent(GameUser user, bool value)
388+
{
389+
this.Write(() =>
390+
{
391+
user.ShowReuploadedContent = value;
392+
});
393+
}
383394

384395
public void ClearForceMatch(GameUser user)
385396
{

Refresh.Database/GameDatabaseProvider.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public void Initialize()
4747
#endif
4848

4949
#if !POSTGRES
50-
protected override ulong SchemaVersion => 167;
50+
protected override ulong SchemaVersion => 169;
5151

5252
protected override string Filename => "refreshGameServer.realm";
5353

@@ -135,7 +135,7 @@ protected override void Migrate(Migration migration, ulong oldVersion)
135135
{
136136
IQueryable<dynamic>? oldUsers = migration.OldRealm.DynamicApi.All("GameUser");
137137
IQueryable<GameUser>? newUsers = migration.NewRealm.All<GameUser>();
138-
if (oldVersion < 165)
138+
if (oldVersion < 169)
139139
for (int i = 0; i < newUsers.Count(); i++)
140140
{
141141
dynamic oldUser = oldUsers.ElementAt(i);
@@ -340,6 +340,9 @@ protected override void Migrate(Migration migration, ulong oldVersion)
340340
}
341341
}
342342
}
343+
344+
if (oldVersion < 169)
345+
newUser.ShowReuploadedContent = true;
343346
}
344347

345348
IQueryable<dynamic>? oldLevels = migration.OldRealm.DynamicApi.All("GameLevel");

Refresh.Database/Models/Users/GameUser.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,15 @@ [Ignored] public GameUserRole Role
135135
}
136136

137137
/// <summary>
138-
/// Whether or not modded content should be shown in level listings
138+
/// Whether modded content should be shown in level listings
139139
/// </summary>
140140
public bool ShowModdedContent { get; set; } = true;
141141

142+
/// <summary>
143+
/// Whether reuploaded content should be shown in level listings
144+
/// </summary>
145+
public bool ShowReuploadedContent { get; set; } = true;
146+
142147
// ReSharper disable once InconsistentNaming
143148
internal byte _Role { get; set; }
144149

Refresh.Database/Query/IApiEditUserRequest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public interface IApiEditUserRequest
1212
bool? UnescapeXmlSequences { get; set; }
1313
string? EmailAddress { get; set; }
1414
bool? ShowModdedContent { get; set; }
15+
bool? ShowReuploadedContent { get; set; }
1516
Visibility? LevelVisibility { get; set; }
1617
Visibility? ProfileVisibility { get; set; }
1718
}

Refresh.Database/Query/LevelFilterSettings.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,15 @@ public class LevelFilterSettings
5858
public TokenGame GameVersion;
5959

6060
/// <summary>
61-
/// Whether or not to force showing/hiding modded content.
61+
/// Whether to force showing/hiding modded content.
6262
/// </summary>
6363
public bool? ShowModdedLevels;
6464

65+
/// <summary>
66+
/// Whether to force showing/hiding reuploaded content.
67+
/// </summary>
68+
public bool? ShowReuploadedLevels;
69+
6570
/// <summary>
6671
/// The seed used for lucky dip/random levels.
6772
/// </summary>
@@ -183,5 +188,15 @@ public LevelFilterSettings(RequestContext context, TokenGame game) : this(game)
183188

184189
this.ShowModdedLevels = showModdedLevels;
185190
}
191+
192+
string? reuploadedFilter = context.QueryString.Get("includeReuploaded");
193+
194+
if (reuploadedFilter != null)
195+
{
196+
if (!bool.TryParse(moddedFilter, out bool showReuploadedLevels))
197+
throw new FormatException("Could not parse reuploaded filter setting because the boolean was invalid.");
198+
199+
this.ShowModdedLevels = showReuploadedLevels;
200+
}
186201
}
187202
}

Refresh.Interfaces.APIv3/Endpoints/DataTypes/Request/ApiUpdateUserRequest.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ public class ApiUpdateUserRequest : IApiEditUserRequest
1818
public string? EmailAddress { get; set; }
1919

2020
public bool? ShowModdedContent { get; set; }
21-
21+
public bool? ShowReuploadedContent { get; set; }
22+
2223
public Visibility? LevelVisibility { get; set; }
2324
public Visibility? ProfileVisibility { get; set; }
2425
}

Refresh.Interfaces.APIv3/Endpoints/DataTypes/Response/Users/ApiExtendedGameUserResponse.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public class ApiExtendedGameUserResponse : IApiResponse, IDataConvertableFrom<Ap
3636
public required bool AllowIpAuthentication { get; set; }
3737

3838
public required bool ShowModdedContent { get; set; }
39+
public required bool ShowReuploadedContent { get; set; }
3940

4041
public required Visibility LevelVisibility { get; set; }
4142
public required Visibility ProfileVisibility { get; set; }
@@ -76,6 +77,7 @@ public class ApiExtendedGameUserResponse : IApiResponse, IDataConvertableFrom<Ap
7677
LevelVisibility = user.LevelVisibility,
7778
ProfileVisibility = user.ProfileVisibility,
7879
ShowModdedContent = user.ShowModdedContent,
80+
ShowReuploadedContent = user.ShowReuploadedContent,
7981
ConnectedToPresenceServer = user.PresenceServerAuthToken != null,
8082
};
8183
}

RefreshTests.GameServer/Tests/Commands/CommandParseTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ private void ParseTest(CommandService service, ReadOnlySpan<char> input, ReadOnl
2121
public void ParsingTest()
2222
{
2323
using Logger logger = new([new NUnitSink()]);
24-
CommandService service = new(logger, new MatchService(logger), new PlayNowService(logger, new PresenceService(logger, new IntegrationConfig())));
24+
CommandService service = new(logger, new PlayNowService(logger, new PresenceService(logger, new IntegrationConfig())));
2525

2626
ParseTest(service, "/parse test", "parse", "test");
2727
ParseTest(service, "/noargs", "noargs", "");
@@ -32,7 +32,7 @@ public void ParsingTest()
3232
public void NoSlashThrows()
3333
{
3434
using Logger logger = new([new NUnitSink()]);
35-
CommandService service = new(logger, new MatchService(logger), new PlayNowService(logger, new PresenceService(logger, new IntegrationConfig())));
35+
CommandService service = new(logger, new PlayNowService(logger, new PresenceService(logger, new IntegrationConfig())));
3636

3737
Assert.That(() => _ = service.ParseCommand("parse test"), Throws.InstanceOf<FormatException>());
3838
}
@@ -41,7 +41,7 @@ public void NoSlashThrows()
4141
public void BlankCommandThrows()
4242
{
4343
using Logger logger = new([new NUnitSink()]);
44-
CommandService service = new(logger, new MatchService(logger), new PlayNowService(logger, new PresenceService(logger, new IntegrationConfig())));
44+
CommandService service = new(logger, new PlayNowService(logger, new PresenceService(logger, new IntegrationConfig())));
4545

4646
Assert.That(() => _ = service.ParseCommand("/ test"), Throws.InstanceOf<FormatException>());
4747
}

0 commit comments

Comments
 (0)