290 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			290 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using EFCore.BulkExtensions;
 | |
| using Microsoft.EntityFrameworkCore;
 | |
| using NodaTime;
 | |
| 
 | |
| namespace DysonNetwork.Sphere.Storage;
 | |
| 
 | |
| public class FileReferenceMigrationService(AppDatabase db)
 | |
| {
 | |
|     public async Task ScanAndMigrateReferences()
 | |
|     {
 | |
|         // Scan Posts for file references
 | |
|         await ScanPosts();
 | |
| 
 | |
|         // Scan Messages for file references
 | |
|         await ScanMessages();
 | |
| 
 | |
|         // Scan Profiles for file references
 | |
|         await ScanProfiles();
 | |
| 
 | |
|         // Scan Chat entities for file references
 | |
|         await ScanChatRooms();
 | |
| 
 | |
|         // Scan Realms for file references
 | |
|         await ScanRealms();
 | |
| 
 | |
|         // Scan Publishers for file references
 | |
|         await ScanPublishers();
 | |
| 
 | |
|         // Scan Stickers for file references
 | |
|         await ScanStickers();
 | |
|     }
 | |
| 
 | |
|     private async Task ScanPosts()
 | |
|     {
 | |
|         var posts = await db.Posts
 | |
|             .Include(p => p.OutdatedAttachments)
 | |
|             .Where(p => p.OutdatedAttachments.Any())
 | |
|             .ToListAsync();
 | |
| 
 | |
|         foreach (var post in posts)
 | |
|         {
 | |
|             var updatedAttachments = new List<CloudFileReferenceObject>();
 | |
| 
 | |
|             foreach (var attachment in post.OutdatedAttachments)
 | |
|             {
 | |
|                 var file = await db.Files.FirstOrDefaultAsync(f => f.Id == attachment.Id);
 | |
|                 if (file != null)
 | |
|                 {
 | |
|                     // Create a reference for the file
 | |
|                     var reference = new CloudFileReference
 | |
|                     {
 | |
|                         FileId = file.Id,
 | |
|                         File = file,
 | |
|                         Usage = "post",
 | |
|                         ResourceId = post.ResourceIdentifier
 | |
|                     };
 | |
| 
 | |
|                     await db.FileReferences.AddAsync(reference);
 | |
|                     updatedAttachments.Add(file.ToReferenceObject());
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     // Keep the existing reference object if file not found
 | |
|                     updatedAttachments.Add(attachment.ToReferenceObject());
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             post.Attachments = updatedAttachments;
 | |
|             db.Posts.Update(post);
 | |
|         }
 | |
| 
 | |
|         await db.SaveChangesAsync();
 | |
|     }
 | |
| 
 | |
|     private async Task ScanMessages()
 | |
|     {
 | |
|         var messages = await db.ChatMessages
 | |
|             .Include(m => m.OutdatedAttachments)
 | |
|             .Where(m => m.OutdatedAttachments.Any())
 | |
|             .ToListAsync();
 | |
| 
 | |
|         var fileReferences = messages.SelectMany(message => message.OutdatedAttachments.Select(attachment =>
 | |
|             new CloudFileReference
 | |
|             {
 | |
|                 FileId = attachment.Id,
 | |
|                 File = attachment,
 | |
|                 Usage = "chat",
 | |
|                 ResourceId = message.ResourceIdentifier,
 | |
|                 CreatedAt = SystemClock.Instance.GetCurrentInstant(),
 | |
|                 UpdatedAt = SystemClock.Instance.GetCurrentInstant()
 | |
|             })
 | |
|         ).ToList();
 | |
| 
 | |
|         foreach (var message in messages)
 | |
|         {
 | |
|             message.Attachments = message.OutdatedAttachments.Select(a => a.ToReferenceObject()).ToList();
 | |
|             db.ChatMessages.Update(message);
 | |
|         }
 | |
| 
 | |
|         await db.BulkInsertAsync(fileReferences);
 | |
|         await db.SaveChangesAsync();
 | |
|     }
 | |
| 
 | |
|     
 | |
| 
 | |
|     private async Task ScanChatRooms()
 | |
|     {
 | |
|         var chatRooms = await db.ChatRooms
 | |
|             .Where(c => c.PictureId != null || c.BackgroundId != null)
 | |
|             .ToListAsync();
 | |
| 
 | |
|         foreach (var chatRoom in chatRooms)
 | |
|         {
 | |
|             if (chatRoom is { PictureId: not null, Picture: null })
 | |
|             {
 | |
|                 var avatarFile = await db.Files.FirstOrDefaultAsync(f => f.Id == chatRoom.PictureId);
 | |
|                 if (avatarFile != null)
 | |
|                 {
 | |
|                     // Create a reference for the avatar file
 | |
|                     var reference = new CloudFileReference
 | |
|                     {
 | |
|                         FileId = avatarFile.Id,
 | |
|                         File = avatarFile,
 | |
|                         Usage = "chatroom.picture",
 | |
|                         ResourceId = chatRoom.ResourceIdentifier
 | |
|                     };
 | |
| 
 | |
|                     await db.FileReferences.AddAsync(reference);
 | |
|                     chatRoom.Picture = avatarFile.ToReferenceObject();
 | |
|                     db.ChatRooms.Update(chatRoom);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (chatRoom is not { BackgroundId: not null, Background: null }) continue;
 | |
|             var bannerFile = await db.Files.FirstOrDefaultAsync(f => f.Id == chatRoom.BackgroundId);
 | |
|             if (bannerFile == null) continue;
 | |
|             {
 | |
|                 // Create a reference for the banner file
 | |
|                 var reference = new CloudFileReference
 | |
|                 {
 | |
|                     FileId = bannerFile.Id,
 | |
|                     File = bannerFile,
 | |
|                     Usage = "chatroom.background",
 | |
|                     ResourceId = chatRoom.ResourceIdentifier
 | |
|                 };
 | |
| 
 | |
|                 await db.FileReferences.AddAsync(reference);
 | |
|                 chatRoom.Background = bannerFile.ToReferenceObject();
 | |
|                 db.ChatRooms.Update(chatRoom);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         await db.SaveChangesAsync();
 | |
|     }
 | |
| 
 | |
|     private async Task ScanRealms()
 | |
|     {
 | |
|         var realms = await db.Realms
 | |
|             .Where(r => r.PictureId != null && r.BackgroundId != null)
 | |
|             .ToListAsync();
 | |
| 
 | |
|         foreach (var realm in realms)
 | |
|         {
 | |
|             // Process avatar if it exists
 | |
|             if (realm is { PictureId: not null, Picture: null })
 | |
|             {
 | |
|                 var avatarFile = await db.Files.FirstOrDefaultAsync(f => f.Id == realm.PictureId);
 | |
|                 if (avatarFile != null)
 | |
|                 {
 | |
|                     // Create a reference for the avatar file
 | |
|                     var reference = new CloudFileReference
 | |
|                     {
 | |
|                         FileId = avatarFile.Id,
 | |
|                         File = avatarFile,
 | |
|                         Usage = "realm.picture",
 | |
|                         ResourceId = realm.ResourceIdentifier
 | |
|                     };
 | |
| 
 | |
|                     await db.FileReferences.AddAsync(reference);
 | |
|                     realm.Picture = avatarFile.ToReferenceObject();
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             // Process banner if it exists
 | |
|             if (realm is { BackgroundId: not null, Background: null })
 | |
|             {
 | |
|                 var bannerFile = await db.Files.FirstOrDefaultAsync(f => f.Id == realm.BackgroundId);
 | |
|                 if (bannerFile != null)
 | |
|                 {
 | |
|                     // Create a reference for the banner file
 | |
|                     var reference = new CloudFileReference
 | |
|                     {
 | |
|                         FileId = bannerFile.Id,
 | |
|                         File = bannerFile,
 | |
|                         Usage = "realm.background",
 | |
|                         ResourceId = realm.ResourceIdentifier
 | |
|                     };
 | |
| 
 | |
|                     await db.FileReferences.AddAsync(reference);
 | |
|                     realm.Background = bannerFile.ToReferenceObject();
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             db.Realms.Update(realm);
 | |
|         }
 | |
| 
 | |
|         await db.SaveChangesAsync();
 | |
|     }
 | |
| 
 | |
|     private async Task ScanPublishers()
 | |
|     {
 | |
|         var publishers = await db.Publishers
 | |
|             .Where(p => p.PictureId != null || p.BackgroundId != null)
 | |
|             .ToListAsync();
 | |
| 
 | |
|         foreach (var publisher in publishers)
 | |
|         {
 | |
|             if (publisher is { PictureId: not null, Picture: null })
 | |
|             {
 | |
|                 var pictureFile = await db.Files.FirstOrDefaultAsync(f => f.Id == publisher.PictureId);
 | |
|                 if (pictureFile != null)
 | |
|                 {
 | |
|                     // Create a reference for the picture file
 | |
|                     var reference = new CloudFileReference
 | |
|                     {
 | |
|                         FileId = pictureFile.Id,
 | |
|                         File = pictureFile,
 | |
|                         Usage = "publisher.picture",
 | |
|                         ResourceId = publisher.Id.ToString()
 | |
|                     };
 | |
| 
 | |
|                     await db.FileReferences.AddAsync(reference);
 | |
|                     publisher.Picture = pictureFile.ToReferenceObject();
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (publisher is { BackgroundId: not null, Background: null })
 | |
|             {
 | |
|                 var backgroundFile = await db.Files.FirstOrDefaultAsync(f => f.Id == publisher.BackgroundId);
 | |
|                 if (backgroundFile != null)
 | |
|                 {
 | |
|                     // Create a reference for the background file
 | |
|                     var reference = new CloudFileReference
 | |
|                     {
 | |
|                         FileId = backgroundFile.Id,
 | |
|                         File = backgroundFile,
 | |
|                         Usage = "publisher.background",
 | |
|                         ResourceId = publisher.ResourceIdentifier
 | |
|                     };
 | |
| 
 | |
|                     await db.FileReferences.AddAsync(reference);
 | |
|                     publisher.Background = backgroundFile.ToReferenceObject();
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             db.Publishers.Update(publisher);
 | |
|         }
 | |
| 
 | |
|         await db.SaveChangesAsync();
 | |
|     }
 | |
| 
 | |
|     private async Task ScanStickers()
 | |
|     {
 | |
|         var stickers = await db.Stickers
 | |
|             .Where(s => s.ImageId != null && s.Image == null)
 | |
|             .ToListAsync();
 | |
| 
 | |
|         foreach (var sticker in stickers)
 | |
|         {
 | |
|             var imageFile = await db.Files.FirstOrDefaultAsync(f => f.Id == sticker.ImageId);
 | |
|             if (imageFile != null)
 | |
|             {
 | |
|                 // Create a reference for the sticker image file
 | |
|                 var reference = new CloudFileReference
 | |
|                 {
 | |
|                     FileId = imageFile.Id,
 | |
|                     File = imageFile,
 | |
|                     Usage = "sticker.image",
 | |
|                     ResourceId = sticker.ResourceIdentifier
 | |
|                 };
 | |
| 
 | |
|                 await db.FileReferences.AddAsync(reference);
 | |
|                 sticker.Image = imageFile.ToReferenceObject();
 | |
|                 db.Stickers.Update(sticker);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         await db.SaveChangesAsync();
 | |
|     }
 | |
| } |