Files
romrepomgr/RomRepoMgr.Core/Workers/DatImporter.cs

221 lines
8.1 KiB
C#
Raw Normal View History

2020-08-22 04:40:39 +01:00
/******************************************************************************
// RomRepoMgr - ROM repository manager
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2020 Natalia Portillo
*******************************************************************************/
using System;
2020-08-22 14:20:59 +01:00
using System.Collections.Generic;
2020-08-22 04:40:39 +01:00
using System.Diagnostics;
2020-08-22 05:14:52 +01:00
using System.IO;
2020-08-22 14:20:59 +01:00
using System.Linq;
2020-08-22 05:14:52 +01:00
using Aaru.Checksums;
2020-08-22 04:40:39 +01:00
using RomRepoMgr.Core.EventArgs;
using RomRepoMgr.Core.Models;
2020-08-22 05:40:50 +01:00
using RomRepoMgr.Database;
using RomRepoMgr.Database.Models;
2020-08-22 04:40:39 +01:00
using SabreTools.Library.DatFiles;
2020-08-22 05:14:52 +01:00
using ErrorEventArgs = RomRepoMgr.Core.EventArgs.ErrorEventArgs;
2020-08-22 04:40:39 +01:00
namespace RomRepoMgr.Core.Workers
{
public sealed class DatImporter
{
2020-08-22 05:14:52 +01:00
readonly string _datFilesPath;
2020-08-22 04:40:39 +01:00
readonly string _datPath;
bool _aborted;
2020-08-22 05:14:52 +01:00
public DatImporter(string datPath)
{
_datPath = datPath;
_datFilesPath = Path.Combine(Settings.Settings.Current.RepositoryPath, "datfiles");
}
2020-08-22 04:40:39 +01:00
public void Import()
{
try
{
SetIndeterminateProgress?.Invoke(this, System.EventArgs.Empty);
SetMessage?.Invoke(this, new MessageEventArgs
{
Message = "Parsing DAT file..."
});
DateTime start = DateTime.UtcNow;
var datFile = DatFile.CreateAndParse(_datPath);
DateTime end = DateTime.UtcNow;
double elapsed = (end - start).TotalSeconds;
2020-08-22 05:14:52 +01:00
SetMessage?.Invoke(this, new MessageEventArgs
{
Message = "Hashing DAT file..."
});
2020-08-22 12:38:21 +01:00
string datHash = Sha384Context.File(_datPath, out byte[] datHashBinary);
string datHash32 = Base32.ToBase32String(datHashBinary);
2020-08-22 05:14:52 +01:00
if(!Directory.Exists(_datFilesPath))
Directory.CreateDirectory(_datFilesPath);
2020-08-22 12:38:21 +01:00
string compressedDatPath = Path.Combine(_datFilesPath, datHash32 + ".lz");
2020-08-22 05:14:52 +01:00
if(File.Exists(compressedDatPath))
{
ErrorOccurred?.Invoke(this, new ErrorEventArgs
{
Message = "DAT file is already in database, not importing duplicates."
});
return;
}
2020-08-22 05:40:50 +01:00
SetMessage?.Invoke(this, new MessageEventArgs
{
Message = "Adding DAT to database..."
});
2020-08-22 12:38:21 +01:00
// TODO: Check if there is a hash in database but not in repo
2020-08-22 05:40:50 +01:00
var romSet = new RomSet
{
Author = datFile.Header.Author,
Comment = datFile.Header.Comment,
Date = datFile.Header.Date,
Description = datFile.Header.Description,
Filename = Path.GetFileName(_datPath),
Homepage = datFile.Header.Homepage,
Name = datFile.Header.Name,
Sha384 = datHash,
Version = datFile.Header.Version,
CreatedOn = DateTime.UtcNow,
UpdatedOn = DateTime.UtcNow
};
Context.Singleton.RomSets.Add(romSet);
Context.Singleton.SaveChanges();
RomSetAdded?.Invoke(this, new RomSetEventArgs
{
RomSet = new RomSetModel
{
Author = romSet.Author,
Comment = romSet.Comment,
Date = romSet.Date,
Description = romSet.Description,
Filename = romSet.Filename,
Homepage = romSet.Homepage,
Name = romSet.Name,
Sha384 = romSet.Sha384,
Version = romSet.Version
}
});
2020-08-22 05:14:52 +01:00
SetMessage?.Invoke(this, new MessageEventArgs
{
Message = "Compressing DAT file..."
});
var datCompress = new Compression();
datCompress.SetProgress += SetProgress;
datCompress.SetProgressBounds += SetProgressBounds;
datCompress.CompressFile(_datPath, compressedDatPath);
2020-08-22 14:20:59 +01:00
SetMessage?.Invoke(this, new MessageEventArgs
{
Message = "Getting machine (game) names..."
});
List<string> machineNames =
(from value in datFile.Items.Values from item in value select item.Machine.Name).Distinct().
ToList();
SetMessage?.Invoke(this, new MessageEventArgs
{
Message = "Adding machines (games)..."
});
SetProgressBounds?.Invoke(this, new ProgressBoundsEventArgs
{
Minimum = 0,
Maximum = machineNames.Count
});
int position = 0;
Dictionary<string, Machine> machines = new Dictionary<string, Machine>();
foreach(string name in machineNames)
{
SetProgress?.Invoke(this, new ProgressEventArgs
{
Value = position
});
var machine = new Machine
{
Name = name,
RomSet = romSet,
CreatedOn = DateTime.UtcNow,
UpdatedOn = DateTime.UtcNow
};
machines[name] = machine;
Context.Singleton.Machines.Add(machine);
position++;
}
SetMessage?.Invoke(this, new MessageEventArgs
{
Message = "Saving changes to database..."
});
SetIndeterminateProgress?.Invoke(this, System.EventArgs.Empty);
Context.Singleton.SaveChanges();
2020-08-22 04:40:39 +01:00
WorkFinished?.Invoke(this, System.EventArgs.Empty);
}
catch(Exception e)
{
if(Debugger.IsAttached)
throw;
ErrorOccurred?.Invoke(this, new ErrorEventArgs
{
Message = "Unhandled exception occurred."
});
}
}
public void Abort() => _aborted = true;
public event EventHandler SetIndeterminateProgress;
public event EventHandler WorkFinished;
public event EventHandler<ErrorEventArgs> ErrorOccurred;
public event EventHandler<ProgressBoundsEventArgs> SetProgressBounds;
public event EventHandler<ProgressEventArgs> SetProgress;
public event EventHandler<MessageEventArgs> SetMessage;
public event EventHandler<RomSetEventArgs> RomSetAdded;
2020-08-22 04:40:39 +01:00
}
}