2020-01-09 22:56:29 +00:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using MongoDB.Bson;
|
|
|
|
|
using MongoDB.Driver;
|
2020-01-11 04:25:55 +00:00
|
|
|
|
using MongoDB.Driver.Linq;
|
2020-01-09 22:56:29 +00:00
|
|
|
|
using Wabbajack.BuildServer.Models;
|
|
|
|
|
using Wabbajack.Common;
|
2020-01-10 04:47:06 +00:00
|
|
|
|
using Wabbajack.VirtualFileSystem;
|
2020-01-09 22:56:29 +00:00
|
|
|
|
|
|
|
|
|
namespace Wabbajack.BuildServer.Controllers
|
|
|
|
|
{
|
|
|
|
|
[Route("/indexed_files")]
|
|
|
|
|
public class IndexedFiles : AControllerBase<IndexedFiles>
|
|
|
|
|
{
|
|
|
|
|
public IndexedFiles(ILogger<IndexedFiles> logger, DBContext db) : base(logger, db)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[HttpGet]
|
2020-01-12 05:00:41 +00:00
|
|
|
|
[Route("{xxHashAsBase64}/meta.ini")]
|
2020-01-11 04:25:55 +00:00
|
|
|
|
public async Task<IActionResult> GetFileMeta(string xxHashAsBase64)
|
|
|
|
|
{
|
|
|
|
|
var id = xxHashAsBase64.FromHex().ToBase64();
|
|
|
|
|
var state = await Db.DownloadStates.AsQueryable()
|
|
|
|
|
.Where(d => d.Hash == id && d.IsValid)
|
|
|
|
|
.OrderByDescending(d => d.LastValidationTime)
|
|
|
|
|
.Take(1)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
if (state.Count == 0)
|
|
|
|
|
return NotFound();
|
|
|
|
|
Response.ContentType = "text/plain";
|
|
|
|
|
return Ok(string.Join("\r\n", state.FirstOrDefault().State.GetMetaIni()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[HttpGet]
|
2020-01-09 22:56:29 +00:00
|
|
|
|
[Route("{xxHashAsBase64}")]
|
2020-01-10 04:47:06 +00:00
|
|
|
|
public async Task<IActionResult> GetFile(string xxHashAsBase64)
|
2020-01-09 22:56:29 +00:00
|
|
|
|
{
|
2020-01-10 02:06:11 +00:00
|
|
|
|
var id = xxHashAsBase64.FromHex().ToBase64();
|
2020-01-09 22:56:29 +00:00
|
|
|
|
var query = new[]
|
|
|
|
|
{
|
|
|
|
|
new BsonDocument("$match",
|
|
|
|
|
new BsonDocument("_id", id)),
|
|
|
|
|
new BsonDocument("$graphLookup",
|
|
|
|
|
new BsonDocument
|
|
|
|
|
{
|
|
|
|
|
{"from", "indexed_files"},
|
|
|
|
|
{"startWith", "$Children.Hash"},
|
|
|
|
|
{"connectFromField", "Hash"},
|
|
|
|
|
{"connectToField", "_id"},
|
|
|
|
|
{"as", "ChildFiles"},
|
|
|
|
|
{"maxDepth", 8},
|
|
|
|
|
{"restrictSearchWithMatch", new BsonDocument()}
|
2020-01-12 05:00:41 +00:00
|
|
|
|
}),
|
|
|
|
|
new BsonDocument("$project",
|
|
|
|
|
new BsonDocument
|
|
|
|
|
{
|
|
|
|
|
// If we return all fields some BSAs will return more that 16MB which is the
|
|
|
|
|
// maximum doc size that can can be returned from MongoDB
|
|
|
|
|
{ "_id", 1 },
|
|
|
|
|
{ "Size", 1 },
|
|
|
|
|
{ "Children.Name", 1 },
|
|
|
|
|
{ "Children.Hash", 1 },
|
|
|
|
|
{ "ChildFiles._id", 1 },
|
|
|
|
|
{ "ChildFiles.Size", 1 },
|
|
|
|
|
{ "ChildFiles.Children.Name", 1 },
|
|
|
|
|
{ "ChildFiles.Children.Hash", 1 },
|
|
|
|
|
{ "ChildFiles.ChildFiles._id", 1 },
|
|
|
|
|
{ "ChildFiles.ChildFiles.Size", 1 },
|
|
|
|
|
{ "ChildFiles.ChildFiles.Children.Name", 1 },
|
|
|
|
|
{ "ChildFiles.ChildFiles.Children.Hash", 1 },
|
|
|
|
|
{ "ChildFiles.ChildFiles.ChildFiles._id", 1 },
|
|
|
|
|
{ "ChildFiles.ChildFiles.ChildFiles.Size", 1 },
|
|
|
|
|
{ "ChildFiles.ChildFiles.ChildFiles.Children.Name", 1 },
|
|
|
|
|
{ "ChildFiles.ChildFiles.ChildFiles.Children.Hash", 1 },
|
|
|
|
|
{ "ChildFiles.ChildFiles.ChildFiles.ChildFiles._id", 1 },
|
|
|
|
|
{ "ChildFiles.ChildFiles.ChildFiles.ChildFiles.Size", 1 },
|
|
|
|
|
{ "ChildFiles.ChildFiles.ChildFiles.ChildFiles.Children.Name", 1 },
|
|
|
|
|
{ "ChildFiles.ChildFiles.ChildFiles.ChildFiles.Children.Hash", 1 },
|
|
|
|
|
{ "ChildFiles.ChildFiles.ChildFiles.ChildFiles.ChildFiles._id", 1 },
|
|
|
|
|
{ "ChildFiles.ChildFiles.ChildFiles.ChildFiles.ChildFiles.Size", 1 }
|
|
|
|
|
})
|
2020-01-09 22:56:29 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var result = await Db.IndexedFiles.AggregateAsync<TreeResult>(query);
|
|
|
|
|
|
|
|
|
|
IndexedVirtualFile Convert(TreeResult t, string Name = null)
|
|
|
|
|
{
|
|
|
|
|
if (t == null)
|
|
|
|
|
return null;
|
|
|
|
|
|
2020-01-10 02:06:11 +00:00
|
|
|
|
Dictionary<string, TreeResult> indexed_children = new Dictionary<string, TreeResult>();
|
2020-01-12 05:00:41 +00:00
|
|
|
|
if (t.ChildFiles != null && t.ChildFiles.Count > 0)
|
2020-01-09 22:56:29 +00:00
|
|
|
|
indexed_children = t.ChildFiles.ToDictionary(t => t.Hash);
|
2020-01-10 02:06:11 +00:00
|
|
|
|
|
2020-01-09 22:56:29 +00:00
|
|
|
|
var file = new IndexedVirtualFile
|
|
|
|
|
{
|
|
|
|
|
Name = Name,
|
|
|
|
|
Size = t.Size,
|
2020-01-10 02:06:11 +00:00
|
|
|
|
Hash = t.Hash,
|
2020-01-12 05:00:41 +00:00
|
|
|
|
Children = t.ChildFiles != null
|
2020-01-10 02:06:11 +00:00
|
|
|
|
? t.Children.Select(child => Convert(indexed_children[child.Hash], child.Name)).ToList()
|
|
|
|
|
: new List<IndexedVirtualFile>()
|
2020-01-09 22:56:29 +00:00
|
|
|
|
};
|
|
|
|
|
return file;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-10 04:47:06 +00:00
|
|
|
|
var first = result.FirstOrDefault();
|
|
|
|
|
if (first == null)
|
|
|
|
|
return NotFound();
|
|
|
|
|
return Ok(Convert(first));
|
2020-01-09 22:56:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class TreeResult : IndexedFile
|
|
|
|
|
{
|
|
|
|
|
public List<TreeResult> ChildFiles { get; set; }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|