mhunt_launcher/lib/Backend/InstallHelper.dart
2025-01-25 12:01:14 +05:30

137 lines
4.3 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'package:crypto/crypto.dart' as crypto;
import 'package:flutter/foundation.dart';
import 'Backend.dart';
import 'DebugHelper.dart';
import 'package:path/path.dart' as Path;
import 'package:http/http.dart' as http;
import 'FileHashEntry.dart';
class InstallHelper{
static String GetFilePath(int id) => Backend.prefs!.getString('${Backend.Games[id].name}_path') ?? '${Path.join(Backend.docPath!.path, Backend.Games[id].name)}';
static String GetValidationSaveKey(int id)=>'${Backend.Games[id].code}_localFileData';
static String? GetSavedValidationData(int id) => Backend.prefs!.getString(GetValidationSaveKey(id));
static Future<List<FileHashEntry>> GetMissingFiles(int gameId, {bool force = false}) async{
List<FileHashEntry> missingFiles = [];
Directory pathDir = Directory(GetFilePath(gameId));
List<FileHashEntry> localFiles = [];
bool usedLocalSave = false;
if(!force){
String? savedData =GetSavedValidationData(gameId);
if(savedData != null){
localFiles = FileHashEntry.listFromJson(savedData);
usedLocalSave=true;
}else{
localFiles = await getHashtable(pathDir);
}
}else{
localFiles = await getHashtable(pathDir);
}
//Get local hashtable
Debug.LogResponse(jsonEncode(localFiles), src:"local files");
//Write to file
if(!usedLocalSave){
String localFilesJson = FileHashEntry.listToJson(localFiles);
Backend.prefs!.setString(GetValidationSaveKey(gameId),localFilesJson);
if(kDebugMode) {
String hashFilePath = Path.join(pathDir.parent.path, "hashes.txt");
File writeJsonFile = File(hashFilePath);
writeJsonFile.writeAsString(localFilesJson);
Debug.Log("Wrote hash into ${hashFilePath}");
}
}
//Get remote hashtable
String link ='${Backend.API_ENDPOINT}${Backend.Games[gameId].code}/get_hashes.php';
var remoteHashResponse = (await http.post(Uri.parse(link)));
// Debug.LogResponse(remoteHashResponse.body.toString(),src: link);
List<FileHashEntry> remoteList = FileHashEntry.listFromJson(remoteHashResponse.body.toString());
//Comapreeee
for(int i = 0; i <remoteList.length;i++) {
bool isLocalGood = false;
for (int j = 0; j < localFiles.length; j++) {
if (localFiles[j].file == remoteList[i].file) {
isLocalGood = localFiles[j].hash == remoteList[i].hash;
break;
}
}
if (!isLocalGood) {
missingFiles.add(remoteList[i]);
}
}
return missingFiles;
}
static Future<List<FileHashEntry>> getHashtable(Directory pathDir) async{
if(!pathDir.existsSync()){return [];}
List<FileSystemEntity> list =await pathDir.list(recursive: true).toList();
List<FileHashEntry> output = [];
for(int i =0; i < list.length; i++){
FileSystemEntity element = list[i];
File file = File(element.path);
if(await file.exists()) {
String hash = await calculateMD5SumAsyncWithCrypto(element.path);
int size = file.lengthSync();
output.add(FileHashEntry(element.path.replaceAll(pathDir.path, ''), hash, size));
// Debug.Log('${element.path}: ${hash}: ${size}');
}
}
return output;
}
static String DOWNLOAD_BIN_ROOT = "https://vps.playpoolstudios.com/metahunt/data/bin/";
static List<String> GetMissingFileLinks(List<FileHashEntry> missingList,int gameId){
List<String> output = [];
missingList.forEach((element) {
output.add(GetFileUrl(element.file, gameId));
});
return output;
}
static String GetFileUrl(String path, int id){
return '${DOWNLOAD_BIN_ROOT}${Backend.Games[id].code}${path.replaceAll('\\', '/')}';
}
static Future<String> calculateMD5SumAsyncWithCrypto(String filePath) async {
var ret = '';
var file = File(filePath);
if (await file.exists()) {
try {
var md5 = crypto.md5;
var hash = await md5.bind(file.openRead()).first;
ret = hash.toString();
// ret = base64.encode(hash.bytes);
} catch (exception) {
print('Unable to evaluate the MD5 sum :$exception');
return '';
}
} else {
print('`$filePath` does not exits so unable to evaluate its MD5 sum.');
return '';
}
return ret;
}
static String GetExeFilePath(int i){
return Path.join(GetFilePath(i), Backend.Games[i].exeName);
}
}