2020-08-01 13:25:32 -07:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
2024-03-04 23:56:05 -05:00
|
|
|
|
using Microsoft.Data.Sqlite;
|
2021-02-02 11:27:42 -08:00
|
|
|
|
using SabreTools.Core;
|
2020-12-08 16:37:08 -08:00
|
|
|
|
using SabreTools.DatFiles;
|
2020-12-08 15:15:41 -08:00
|
|
|
|
using SabreTools.DatItems;
|
2021-02-02 10:23:43 -08:00
|
|
|
|
using SabreTools.DatItems.Formats;
|
2020-12-10 23:24:09 -08:00
|
|
|
|
using SabreTools.DatTools;
|
2020-12-12 13:40:46 -08:00
|
|
|
|
using SabreTools.FileTypes;
|
2024-03-04 23:56:05 -05:00
|
|
|
|
using SabreTools.Hashing;
|
2020-12-07 13:57:26 -08:00
|
|
|
|
using SabreTools.Help;
|
2020-08-01 13:25:32 -07:00
|
|
|
|
|
|
|
|
|
|
namespace RombaSharp.Features
|
|
|
|
|
|
{
|
|
|
|
|
|
internal class Archive : BaseFeature
|
|
|
|
|
|
{
|
|
|
|
|
|
public const string Value = "Archive";
|
|
|
|
|
|
|
|
|
|
|
|
public Archive()
|
|
|
|
|
|
{
|
|
|
|
|
|
Name = Value;
|
2024-07-18 01:06:40 -04:00
|
|
|
|
Flags.AddRange(["archive"]);
|
2020-08-01 13:25:32 -07:00
|
|
|
|
Description = "Adds ROM files from the specified directories to the ROM archive.";
|
2020-12-07 13:57:26 -08:00
|
|
|
|
_featureType = ParameterType.Flag;
|
2020-08-01 13:25:32 -07:00
|
|
|
|
LongDescription = @"Adds ROM files from the specified directories to the ROM archive.
|
|
|
|
|
|
Traverses the specified directory trees looking for zip files and normal files.
|
|
|
|
|
|
Unpacked files will be stored as individual entries. Prior to unpacking a zip
|
|
|
|
|
|
file, the external SHA1 is checked against the DAT index.
|
|
|
|
|
|
If -only-needed is set, only those files are put in the ROM archive that
|
|
|
|
|
|
have a current entry in the DAT index.";
|
|
|
|
|
|
|
2021-02-03 11:10:19 -08:00
|
|
|
|
// Common Features
|
|
|
|
|
|
AddCommonFeatures();
|
|
|
|
|
|
|
2020-08-01 13:25:32 -07:00
|
|
|
|
AddFeature(OnlyNeededFlag);
|
|
|
|
|
|
AddFeature(ResumeStringInput);
|
|
|
|
|
|
AddFeature(IncludeZipsInt32Input); // Defaults to 0
|
|
|
|
|
|
AddFeature(WorkersInt32Input);
|
|
|
|
|
|
AddFeature(IncludeGZipsInt32Input); // Defaults to 0
|
|
|
|
|
|
AddFeature(Include7ZipsInt32Input); // Defaults to 0
|
|
|
|
|
|
AddFeature(SkipInitialScanFlag);
|
|
|
|
|
|
AddFeature(UseGolangZipFlag);
|
|
|
|
|
|
AddFeature(NoDbFlag);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-03-05 20:26:38 -05:00
|
|
|
|
public override bool ProcessFeatures(Dictionary<string, SabreTools.Help.Feature?> features)
|
2020-08-01 13:25:32 -07:00
|
|
|
|
{
|
2021-03-19 20:52:11 -07:00
|
|
|
|
// If the base fails, just fail out
|
|
|
|
|
|
if (!base.ProcessFeatures(features))
|
|
|
|
|
|
return false;
|
2020-08-01 13:25:32 -07:00
|
|
|
|
|
|
|
|
|
|
// Get the archive scanning level
|
|
|
|
|
|
// TODO: Remove usage
|
|
|
|
|
|
int sevenzip = GetInt32(features, Include7ZipsInt32Value);
|
|
|
|
|
|
int gz = GetInt32(features, IncludeGZipsInt32Value);
|
|
|
|
|
|
int zip = GetInt32(features, IncludeZipsInt32Value);
|
|
|
|
|
|
|
|
|
|
|
|
// Get feature flags
|
|
|
|
|
|
bool noDb = GetBoolean(features, NoDbValue);
|
|
|
|
|
|
bool onlyNeeded = GetBoolean(features, OnlyNeededValue);
|
|
|
|
|
|
|
|
|
|
|
|
// First we want to get just all directories from the inputs
|
|
|
|
|
|
List<string> onlyDirs = new List<string>();
|
|
|
|
|
|
foreach (string input in Inputs)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Directory.Exists(input))
|
|
|
|
|
|
onlyDirs.Add(Path.GetFullPath(input));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Then process all of the input directories into an internal DAT
|
|
|
|
|
|
DatFile df = DatFile.Create();
|
|
|
|
|
|
foreach (string dir in onlyDirs)
|
|
|
|
|
|
{
|
2024-03-04 23:56:05 -05:00
|
|
|
|
DatFromDir.PopulateFromDir(df, dir, asFiles: TreatAsFile.NonArchive, hashes: [HashType.CRC32, HashType.MD5, HashType.SHA1]);
|
|
|
|
|
|
DatFromDir.PopulateFromDir(df, dir, asFiles: TreatAsFile.All, hashes: [HashType.CRC32, HashType.MD5, HashType.SHA1]);
|
2020-08-01 13:25:32 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Create an empty Dat for files that need to be rebuilt
|
|
|
|
|
|
DatFile need = DatFile.Create();
|
|
|
|
|
|
|
|
|
|
|
|
// Open the database connection
|
|
|
|
|
|
SqliteConnection dbc = new SqliteConnection(_connectionString);
|
|
|
|
|
|
dbc.Open();
|
|
|
|
|
|
|
|
|
|
|
|
// Now that we have the Dats, add the files to the database
|
|
|
|
|
|
string crcquery = "INSERT OR IGNORE INTO crc (crc) VALUES";
|
|
|
|
|
|
string md5query = "INSERT OR IGNORE INTO md5 (md5) VALUES";
|
|
|
|
|
|
string sha1query = "INSERT OR IGNORE INTO sha1 (sha1, depot) VALUES";
|
|
|
|
|
|
string crcsha1query = "INSERT OR IGNORE INTO crcsha1 (crc, sha1) VALUES";
|
|
|
|
|
|
string md5sha1query = "INSERT OR IGNORE INTO md5sha1 (md5, sha1) VALUES";
|
|
|
|
|
|
|
|
|
|
|
|
foreach (string key in df.Items.Keys)
|
|
|
|
|
|
{
|
2024-03-05 20:26:38 -05:00
|
|
|
|
ConcurrentList<DatItem>? datItems = df.Items[key];
|
|
|
|
|
|
if (datItems == null)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2020-08-01 13:25:32 -07:00
|
|
|
|
foreach (Rom rom in datItems)
|
|
|
|
|
|
{
|
|
|
|
|
|
// If we care about if the file exists, check the databse first
|
|
|
|
|
|
if (onlyNeeded && !noDb)
|
|
|
|
|
|
{
|
|
|
|
|
|
string query = "SELECT * FROM crcsha1 JOIN md5sha1 ON crcsha1.sha1=md5sha1.sha1"
|
2024-03-11 15:46:44 -04:00
|
|
|
|
+ $" WHERE crcsha1.crc=\"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.CRCKey)}\""
|
|
|
|
|
|
+ $" OR md5sha1.md5=\"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.MD5Key)}\""
|
|
|
|
|
|
+ $" OR md5sha1.sha1=\"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.SHA1Key)}\"";
|
2020-08-01 13:25:32 -07:00
|
|
|
|
SqliteCommand slc = new SqliteCommand(query, dbc);
|
|
|
|
|
|
SqliteDataReader sldr = slc.ExecuteReader();
|
|
|
|
|
|
|
|
|
|
|
|
if (sldr.HasRows)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Add to the queries
|
2024-03-11 15:46:44 -04:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.CRCKey)))
|
|
|
|
|
|
crcquery += $" (\"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.CRCKey)}\"),";
|
2020-08-01 13:25:32 -07:00
|
|
|
|
|
2024-03-11 15:46:44 -04:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.MD5Key)))
|
|
|
|
|
|
md5query += $" (\"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.MD5Key)}\"),";
|
2020-08-01 13:25:32 -07:00
|
|
|
|
|
2024-03-11 15:46:44 -04:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.SHA1Key)))
|
2020-08-01 13:25:32 -07:00
|
|
|
|
{
|
2024-03-11 15:46:44 -04:00
|
|
|
|
sha1query += $" (\"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.SHA1Key)}\", \"{_depots!.Keys.ToList()[0]}\"),";
|
2020-08-01 13:25:32 -07:00
|
|
|
|
|
2024-03-11 15:46:44 -04:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.CRCKey)))
|
|
|
|
|
|
crcsha1query += $" (\"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.CRCKey)}\", \"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.SHA1Key)}\"),";
|
2020-08-01 13:25:32 -07:00
|
|
|
|
|
2024-03-11 15:46:44 -04:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.MD5Key)))
|
|
|
|
|
|
md5sha1query += $" (\"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.MD5Key)}\", \"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.SHA1Key)}\"),";
|
2020-08-01 13:25:32 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Add to the Dat
|
|
|
|
|
|
need.Items.Add(key, rom);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// Otherwise, just add the file to the list
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Add to the queries
|
|
|
|
|
|
if (!noDb)
|
|
|
|
|
|
{
|
2024-03-11 15:46:44 -04:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.CRCKey)))
|
|
|
|
|
|
crcquery += $" (\"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.CRCKey)}\"),";
|
2020-08-01 13:25:32 -07:00
|
|
|
|
|
2024-03-11 15:46:44 -04:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.MD5Key)))
|
|
|
|
|
|
md5query += $" (\"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.MD5Key)}\"),";
|
2020-08-01 13:25:32 -07:00
|
|
|
|
|
2024-03-11 15:46:44 -04:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.SHA1Key)))
|
2020-08-01 13:25:32 -07:00
|
|
|
|
{
|
2024-03-11 15:46:44 -04:00
|
|
|
|
sha1query += $" (\"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.SHA1Key)}\", \"{_depots!.Keys.ToList()[0]}\"),";
|
2020-08-01 13:25:32 -07:00
|
|
|
|
|
2024-03-11 15:46:44 -04:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.CRCKey)))
|
|
|
|
|
|
crcsha1query += $" (\"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.CRCKey)}\", \"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.SHA1Key)}\"),";
|
2020-08-01 13:25:32 -07:00
|
|
|
|
|
2024-03-11 15:46:44 -04:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.MD5Key)))
|
|
|
|
|
|
md5sha1query += $" (\"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.MD5Key)}\", \"{rom.GetStringFieldValue(SabreTools.Models.Metadata.Rom.SHA1Key)}\"),";
|
2020-08-01 13:25:32 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Add to the Dat
|
|
|
|
|
|
need.Items.Add(key, rom);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Now run the queries, if they're populated
|
|
|
|
|
|
if (crcquery != "INSERT OR IGNORE INTO crc (crc) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
SqliteCommand slc = new SqliteCommand(crcquery.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
slc.Dispose();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (md5query != "INSERT OR IGNORE INTO md5 (md5) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
SqliteCommand slc = new SqliteCommand(md5query.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
slc.Dispose();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (sha1query != "INSERT OR IGNORE INTO sha1 (sha1, depot) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
SqliteCommand slc = new SqliteCommand(sha1query.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
slc.Dispose();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (crcsha1query != "INSERT OR IGNORE INTO crcsha1 (crc, sha1) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
SqliteCommand slc = new SqliteCommand(crcsha1query.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
slc.Dispose();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (md5sha1query != "INSERT OR IGNORE INTO md5sha1 (md5, sha1) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
SqliteCommand slc = new SqliteCommand(md5sha1query.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
slc.Dispose();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Create the sorting object to use and rebuild the needed files
|
2020-12-10 14:31:00 -08:00
|
|
|
|
Rebuilder.RebuildGeneric(
|
2020-12-10 11:07:36 -08:00
|
|
|
|
need,
|
2020-08-02 13:44:45 -07:00
|
|
|
|
onlyDirs,
|
2024-03-05 20:26:38 -05:00
|
|
|
|
outDir: _depots!.Keys.ToList()[0],
|
2020-08-02 13:44:45 -07:00
|
|
|
|
outputFormat: OutputFormat.TorrentGzipRomba,
|
2020-09-18 10:54:34 -07:00
|
|
|
|
asFiles: TreatAsFile.NonArchive);
|
2024-07-17 15:46:42 -04:00
|
|
|
|
|
2021-03-19 20:52:11 -07:00
|
|
|
|
return true;
|
2020-08-01 13:25:32 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|