Files
hasaddon/onedrive-backup/Hass/HassioClient.cs
T
admins d70d81ebdf OneDrive Backup
OneDrive Backup
2023-07-28 22:36:06 +07:00

226 lines
8.9 KiB
C#

using hassio_onedrive_backup.Contracts;
using hassio_onedrive_backup.Hass.Events;
using hassio_onedrive_backup.Storage;
using Newtonsoft.Json;
using onedrive_backup.Contracts;
using System.Globalization;
using System.Net.Http.Headers;
using System.Text;
using static hassio_onedrive_backup.Contracts.HassAddonsResponse;
using static hassio_onedrive_backup.Contracts.HassBackupsResponse;
namespace hassio_onedrive_backup.Hass
{
internal class HassioClient : IHassioClient
{
private const string Supervisor_Base_Uri_Str = "http://supervisor";
private const string Hass_Base_Uri_Str = "http://supervisor/core/api";
private readonly HttpClient _httpClient;
public HassioClient(string token, int hassioTimeout)
{
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
_httpClient.Timeout = TimeSpan.FromMinutes(hassioTimeout);
}
public async Task<bool> DeleteBackupAsync(Backup backup)
{
try
{
Uri uri = new Uri(Supervisor_Base_Uri_Str + $"/backups/{backup.Slug}");
await _httpClient.DeleteAsync(uri);
}
catch (Exception ex)
{
ConsoleLogger.LogError($"Error deleting backup {backup.Slug}. {ex}");
return false;
}
return true;
}
public async Task<List<Backup>> GetBackupsAsync(Predicate<Backup> filter)
{
Uri uri = new Uri(Supervisor_Base_Uri_Str + "/backups");
var response = await GetJsonResponseAsync<HassBackupsResponse>(uri);
if (response.Result.Equals("ok", StringComparison.OrdinalIgnoreCase) == false)
{
throw new InvalidOperationException($"Failed getting Backups from Supervisor. Result: {response.Result}");
}
var backups = response.DataProperty.Backups;
return filter != null ? backups.Where(backup => filter(backup)).ToList() : backups.ToList();
}
public async Task<bool> CreateBackupAsync(string backupName, bool appendTimestamp = true, bool compressed = true, string? password = null, IEnumerable<string>? folders = null, IEnumerable<string>? addons = null)
{
DateTime timeStamp = DateTimeHelper.Instance!.Now;
const string dt_format = "yyyy-MM-dd-HH-mm";
string? payloadStr;
Uri? uri;
string finalBackupName = appendTimestamp ? $"{backupName}_{timeStamp.ToString(dt_format, CultureInfo.CurrentCulture)}" : backupName;
// Full Backup
if (folders == null && addons == null)
{
uri = new Uri(Supervisor_Base_Uri_Str + "/backups/new/full");
var fullPayload = new
{
name = finalBackupName,
compressed = compressed,
password = password
};
payloadStr = JsonConvert.SerializeObject(fullPayload, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
ConsoleLogger.LogInfo("Starting full local backup");
}
// Partial Backup
else
{
uri = new Uri(Supervisor_Base_Uri_Str + "/backups/new/partial");
var partialPayload = new
{
name = finalBackupName,
compressed = compressed,
password = password,
homeassistant = true,
addons = addons,
folders = folders
};
payloadStr = JsonConvert.SerializeObject(partialPayload, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
ConsoleLogger.LogInfo("Starting partial local backup");
}
try
{
await _httpClient.PostAsync(uri, new StringContent(payloadStr, Encoding.UTF8, "application/json"));
ConsoleLogger.LogInfo("Backup complete");
}
catch (TaskCanceledException tce)
{
if (tce.InnerException is TimeoutException)
{
ConsoleLogger.LogError($"Backup request timed out. {tce}");
ConsoleLogger.LogError($"Increase the timeout value in configuration");
return false;
}
}
catch (Exception ex)
{
ConsoleLogger.LogError($"Failed creating new backup. {ex}");
return false;
}
return true;
}
public async Task<bool> UploadBackupAsync(string filePath)
{
try
{
Uri uri = new Uri(Supervisor_Base_Uri_Str + "/backups/new/upload");
using var multiPartFormContent = new MultipartFormDataContent();
var fsContent = new StreamContent(System.IO.File.OpenRead(filePath));
multiPartFormContent.Add(fsContent, name: "file", fileName: filePath);
var response = await _httpClient.PostAsync(uri, multiPartFormContent);
response.EnsureSuccessStatusCode();
}
catch (Exception ex)
{
ConsoleLogger.LogError($"Error uploading backup to Home Assistant. {ex}");
return false;
}
return true;
}
public async Task SendPersistentNotificationAsync(string message)
{
try
{
Uri uri = new Uri(Hass_Base_Uri_Str + "/services/notify/persistent_notification");
var payload = new
{
message = message,
title = "hassio-onedrive-backup"
};
string payloadStr = JsonConvert.SerializeObject(payload);
await _httpClient.PostAsync(uri, new StringContent(payloadStr, Encoding.UTF8, "application/json"));
}
catch (Exception ex)
{
ConsoleLogger.LogError($"Failed sending persistent notification. {ex}");
}
}
public async Task<List<Addon>> GetAddonsAsync()
{
Uri uri = new Uri(Supervisor_Base_Uri_Str + "/addons");
var response = await GetJsonResponseAsync<HassAddonsResponse>(uri);
var ret = response.DataProperty.Addons.ToList();
return ret;
}
public async Task UpdateHassEntityStateAsync(string entityId, string payload)
{
Uri uri = new Uri(Hass_Base_Uri_Str + $"/states/{entityId}");
await _httpClient.PostAsync(uri, new StringContent(payload, Encoding.UTF8, "application/json"));
}
public async Task PublishEventAsync(OneDriveEvents eventType, string payload = "")
{
Uri uri = new Uri(Hass_Base_Uri_Str + $"/events/onedrive.{eventType}");
await _httpClient.PostAsync(uri, new StringContent(payload, Encoding.UTF8, "application/json"));
}
public async Task<string> DownloadBackupAsync(string backupSlug)
{
ConsoleLogger.LogInfo($"Fetching Local Backup (Slug:{backupSlug})");
Uri uri = new Uri(Supervisor_Base_Uri_Str + $"/backups/{backupSlug}/download");
var fileInfo = new FileInfo($"{LocalStorage.TempFolder}/{backupSlug}.tar");
await using var memStream = await _httpClient.GetStreamAsync(uri);
using var fileStream = System.IO.File.Create(fileInfo.FullName);
await memStream.CopyToAsync(fileStream);
ConsoleLogger.LogInfo($"Backup ({backupSlug}) fetched successfully");
return fileInfo.FullName;
}
public async Task<string> GetTimeZoneAsync()
{
Uri uri = new Uri(Supervisor_Base_Uri_Str + "/supervisor/info");
var response = await GetJsonResponseAsync<HassSupervisorInfoResponse>(uri);
var ret = response.DataProperty.Timezone;
return ret;
}
private async Task<T> GetJsonResponseAsync<T>(Uri uri)
{
string response = await _httpClient.GetStringAsync(uri);
T ret = JsonConvert.DeserializeObject<T>(response)!;
return ret;
}
public async Task<HassAddonInfoResponse> GetAddonInfo(string slug)
{
Uri uri = new Uri(Supervisor_Base_Uri_Str + $"/addons/{slug}/info");
var response = await GetJsonResponseAsync<HassAddonInfoResponse>(uri);
return response;
}
}
}