Mesen-X/GUI.NET/GoogleDriveIntegration/CloudSyncHelper.cs

157 lines
4.7 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Mesen.GUI.Config;
namespace Mesen.GUI.GoogleDriveIntegration
{
public class CloudSyncHelper
{
private static object _lock = new object();
private static GoogleDriveAccessor _accessor;
public static bool Syncing
{
get
{
bool lockTaken = false;
System.Threading.Monitor.TryEnter(_lock, ref lockTaken);
if(lockTaken) {
System.Threading.Monitor.Exit(_lock);
}
return !lockTaken;
}
}
public static bool Sync()
{
if(!System.Threading.Monitor.TryEnter(_lock)) {
//Already syncing, return when on-going sync is done
lock(_lock) {
return true;
}
} else {
try {
string googleDriveFolder = Path.Combine(ConfigManager.HomeFolder, "GoogleDrive");
if(!Directory.Exists(googleDriveFolder) || Directory.EnumerateFiles(googleDriveFolder).Where((string filename) => filename.Contains("TokenResponse")).Count() == 0) {
//Sync token has been deleted, disable sync
ConfigManager.Config.PreferenceInfo.CloudSaveIntegration = false;
ConfigManager.ApplyChanges();
return false;
}
InteropEmu.DisplayMessage("GoogleDrive", "SynchronizationStarted");
using(_accessor = new GoogleDriveAccessor()) {
FileDownloadResult result = CloudSyncHelper.DownloadData();
if(result == FileDownloadResult.Error) {
InteropEmu.DisplayMessage("GoogleDrive", "SynchronizationFailed");
return false;
}
CloudSyncHelper.UploadData();
InteropEmu.DisplayMessage("GoogleDrive", "SynchronizationCompleted");
ConfigManager.Config.PreferenceInfo.CloudLastSync = DateTime.Now;
ConfigManager.ApplyChanges();
return true;
}
} finally {
System.Threading.Monitor.Exit(_lock);
}
}
}
public static bool EnableSync()
{
using(_accessor = new GoogleDriveAccessor()) {
bool result = _accessor.AcquireToken();
if(result) {
ConfigManager.Config.PreferenceInfo.CloudSaveIntegration = true;
ConfigManager.ApplyChanges();
}
return result;
}
}
public static void DisableSync()
{
using(_accessor = new GoogleDriveAccessor()) {
_accessor.RevokeToken();
}
ConfigManager.Config.PreferenceInfo.CloudSaveIntegration = false;
ConfigManager.ApplyChanges();
}
private static bool UploadData()
{
using(MemoryStream stream = CloudSyncHelper.GetDataStream()) {
return _accessor.UploadFile(stream, "MesenData.zip");
}
}
private static FileDownloadResult DownloadData()
{
using(MemoryStream stream = new MemoryStream()) {
FileDownloadResult result = _accessor.DownloadFile(stream, "MesenData.zip");
if(result == FileDownloadResult.OK) {
try {
stream.Position = 0;
string homeFolder = ConfigManager.HomeFolder;
//Make sure the folders exist
string saveFolder = ConfigManager.SaveFolder;
string saveStateFolder = ConfigManager.SaveStateFolder;
using(ZipArchive archive = new ZipArchive(stream)) {
foreach(ZipArchiveEntry entry in archive.Entries) {
if(!string.IsNullOrWhiteSpace(entry.Name)) {
string[] fileAndFolder = entry.FullName.Split('/');
string fileName = Path.Combine(homeFolder, fileAndFolder[0], fileAndFolder[1]);
if(!File.Exists(fileName) || File.GetLastWriteTime(fileName) < entry.LastWriteTime.ToLocalTime()) {
//File on server is more recent, or doesn't exist on local computer, extract it
try {
entry.ExtractToFile(fileName, true);
} catch {
//Files might be opened by another program or not read-only, etc.
}
}
}
}
}
} catch {
result = FileDownloadResult.FileCorrupted;
}
} else if(_accessor.Revoked) {
ConfigManager.Config.PreferenceInfo.CloudSaveIntegration = false;
ConfigManager.ApplyChanges();
}
return result;
}
}
private static MemoryStream GetDataStream()
{
MemoryStream outputStream = new MemoryStream();
using(ZipArchive archive = new ZipArchive(outputStream, ZipArchiveMode.Create, true)) {
archive.CreateEntry("Saves/");
foreach(string filename in System.IO.Directory.EnumerateFiles(ConfigManager.SaveFolder, "*.sav", System.IO.SearchOption.AllDirectories)) {
archive.CreateEntryFromFile(filename, "Saves/" + System.IO.Path.GetFileName(filename));
}
archive.CreateEntry("SaveStates/");
foreach(string filename in System.IO.Directory.EnumerateFiles(ConfigManager.SaveStateFolder, "*.mst", System.IO.SearchOption.AllDirectories)) {
archive.CreateEntryFromFile(filename, "SaveStates/" + System.IO.Path.GetFileName(filename));
}
}
return outputStream;
}
}
}