11using Bunkum . Core ;
22using Bunkum . Core . Endpoints ;
3+ using Bunkum . Core . RateLimit ;
34using Bunkum . Core . Responses ;
45using Bunkum . Listener . Protocol ;
56using Bunkum . Protocols . Http ;
1112using Refresh . Database . Models . Levels ;
1213using Refresh . Database . Models . Playlists ;
1314using Refresh . Database . Models . Users ;
15+ using static Refresh . Core . RateLimits . PlaylistEndpointLimits ;
1416using Refresh . Interfaces . Game . Types . Levels ;
1517using Refresh . Interfaces . Game . Types . Lists ;
1618using Refresh . Interfaces . Game . Types . Playlists ;
@@ -19,9 +21,38 @@ namespace Refresh.Interfaces.Game.Endpoints.Playlists;
1921
2022public class Lbp1PlaylistEndpoints : EndpointGroup
2123{
24+ /// <summary>
25+ /// Validate the playlist icon. If it's blank, an invalid GUID or a remote asset which doesn't exist on the server, reset to blank hash
26+ /// and do not return an error to not upset the game in certain cases (also because the user cannot choose the icon when creating a playlist).
27+ /// </summary>
28+ private string ValidateIconHash ( string iconHash , DataContext dataContext )
29+ {
30+ if ( iconHash . IsBlankHash ( ) )
31+ {
32+ return "0" ;
33+ }
34+ else if ( iconHash . StartsWith ( 'g' ) )
35+ {
36+ //Parse out the GUID
37+ long guid = long . Parse ( iconHash . AsSpan ( ) [ 1 ..] ) ;
38+
39+ if ( ! dataContext . GuidChecker . IsTextureGuid ( dataContext . Game , guid ) )
40+ {
41+ return "0" ;
42+ }
43+ }
44+ else if ( ! dataContext . DataStore . ExistsInStore ( iconHash ) )
45+ {
46+ return "0" ;
47+ }
48+
49+ return iconHash ;
50+ }
51+
2252 // Creates a playlist, with an optional parent ID
2353 [ GameEndpoint ( "createPlaylist" , HttpMethods . Post , ContentType . Xml ) ]
2454 [ RequireEmailVerified ]
55+ [ RateLimitSettings ( UploadTimeoutDuration , MaxCreateAmount , UploadBlockDuration , CreateBucket ) ]
2556 public Response CreatePlaylist ( RequestContext context , DataContext dataContext , GameServerConfig config , SerializedLbp1Playlist body )
2657 {
2758 GameUser user = dataContext . User ! ;
@@ -57,6 +88,9 @@ public Response CreatePlaylist(RequestContext context, DataContext dataContext,
5788 if ( body . Description . Length > UgcLimits . DescriptionLimit )
5889 body . Description = body . Description [ ..UgcLimits . DescriptionLimit ] ;
5990
91+ // Validate icon
92+ body . Icon = this . ValidateIconHash ( body . Icon , dataContext ) ;
93+
6094 // Create the playlist, marking it as the root playlist if the user does not have one set already
6195 GamePlaylist playlist = dataContext . Database . CreatePlaylist ( user , body , rootPlaylist == null ) ;
6296
@@ -150,12 +184,13 @@ public Response CreatePlaylist(RequestContext context, DataContext dataContext,
150184
151185 [ GameEndpoint ( "setPlaylistMetaData/{id}" , HttpMethods . Post , ContentType . Xml ) ]
152186 [ RequireEmailVerified ]
153- public Response UpdatePlaylistMetadata ( RequestContext context , GameServerConfig config , GameDatabaseContext database , GameUser user , int id , SerializedLbp1Playlist body )
187+ [ RateLimitSettings ( UploadTimeoutDuration , MaxUpdateAmount , UploadBlockDuration , UpdateBucket ) ]
188+ public Response UpdatePlaylistMetadata ( RequestContext context , GameServerConfig config , DataContext dataContext , GameUser user , int id , SerializedLbp1Playlist body )
154189 {
155190 if ( user . IsWriteBlocked ( config ) )
156191 return Unauthorized ;
157192
158- GamePlaylist ? playlist = database . GetPlaylistById ( id ) ;
193+ GamePlaylist ? playlist = dataContext . Database . GetPlaylistById ( id ) ;
159194 if ( playlist == null )
160195 return NotFound ;
161196
@@ -170,7 +205,10 @@ public Response UpdatePlaylistMetadata(RequestContext context, GameServerConfig
170205 if ( body . Description . Length > UgcLimits . DescriptionLimit )
171206 body . Description = body . Description [ ..UgcLimits . DescriptionLimit ] ;
172207
173- database . UpdatePlaylist ( playlist , body ) ;
208+ // Validate icon
209+ body . Icon = this . ValidateIconHash ( body . Icon , dataContext ) ;
210+
211+ dataContext . Database . UpdatePlaylist ( playlist , body ) ;
174212 return OK ;
175213 }
176214
0 commit comments