using System.Collections.ObjectModel; using System.Net.Http.Headers; using Avalonia.Media; using Avalonia.Threading; using CommunityToolkit.Mvvm.DependencyInjection; using DynamicData; using DynamicData.Binding; using HetznerCloudApi; using Material.Icons; using Newtonsoft.Json.Linq; using PSCHelpdesk.Plugins.HetznerServer.Models; using PSCHelpdesk.Shared.Service; using PSCHelpdesk.Shared.Setting; using PSCHelpdesk.Shared.Tasks; using ReactiveUI; using Renci.SshNet; namespace PSCHelpdesk.Plugins.HetznerServer.Service; public class ServerService: IServerService { public SourceCache SourceCache = new (x => x.ServerId); private SettingsManager _settingsManager; private readonly DispatcherTimer _reloadTimer = new DispatcherTimer(); private string _searchText = string.Empty; private ITaskManager _taskManager; private readonly IToastManager? _toastManager; public ServerService() { _settingsManager = (SettingsManager)Ioc.Default.GetService(); _taskManager = Ioc.Default.GetService(); _toastManager = (IToastManager)Ioc.Default.GetService(); this._reloadTimer.Tick += (sender, args) => { this.reloadServerStatus(); }; _reloadTimer.Interval = TimeSpan.FromMinutes(10); _reloadTimer.Start(); reloadServer(); } private async Task reloadServer() { var settings = new Settings(); _settingsManager.LoadPluginSettings("HetznerSettings", settings); if (settings.HetznerApiKey != "") { HetznerCloudClient hetznerCloudClient = new HetznerCloudClient(settings.HetznerApiKey); List list = await hetznerCloudClient.Server.Get(); foreach (var server in list) { var uiDispatcher = Ioc.Default.GetService(); await uiDispatcher.InvokeAsync(() => { SourceCache.AddOrUpdate(new Server(server.Id, server.Name, server.ServerType.Name, server.Status, server.PublicNet.Ipv4.Ip, server.PublicNet.Ipv6.Ip)); }); } } await Task.Run(async () => await this.reloadServerStatus()); } private async Task reloadServerStatus() { var uiDispatcher = Ioc.Default.GetService(); await uiDispatcher.InvokeAsync(() => { _reloadTimer.Stop(); }); var settings = new Settings(); _settingsManager.LoadPluginSettings("HetznerSettings", settings); foreach (Server serv in SourceCache.Items) { if (settings.ServerSettings.Count(e => e.ServerId == serv.ServerId) > 0) { serv.FastBillId = settings.ServerSettings.First(e => e.ServerId == serv.ServerId).FastBillId; serv.FastBillNr = settings.ServerSettings.First(e => e.ServerId == serv.ServerId).FastBillNr; serv.PscApiKey = settings.ServerSettings.First(e => e.ServerId == serv.ServerId).PscApiKey; } var connectionInfo = new ConnectionInfo(serv.Ipv4, "root", new PrivateKeyAuthenticationMethod("root", new PrivateKeyFile(this._settingsManager.CoreSettings.PrivateSSHKeyPath))); using (var client = new SshClient(connectionInfo)) { try { client.Connect(); var command = client.RunCommand("borgmatic info --json"); if (command.ExitStatus == 0) { serv.HasBackup = true; JArray borgMatic = JArray.Parse(command.Result); await uiDispatcher.InvokeAsync(() => { serv.BackupLastModified = DateTime.Parse(borgMatic[0]["repository"]["last_modified"].ToString()); }); } command = client.RunCommand("docker inspect psc_mongodb_1"); if (command.ExitStatus == 0) { JArray mongoDB = JArray.Parse(command.Result); var mongoDBEnvArray = mongoDB[0]["Config"]["Env"]; foreach (String entry in mongoDBEnvArray) { var mongodDBexploded = entry.Split("="); if (mongodDBexploded[0] == "MONGO_VERSION") { serv.MongoVersion = mongodDBexploded[1]; } } } command = client.RunCommand("docker inspect psc_mysql_1"); if (command.ExitStatus == 0) { JArray mongoDB = JArray.Parse(command.Result); var mongoDBEnvArray = mongoDB[0]["Config"]["Env"]; foreach (String entry in mongoDBEnvArray) { var mongodDBexploded = entry.Split("="); if (mongodDBexploded[0] == "MARIADB_VERSION") { serv.MysqlVersion = mongodDBexploded[1]; } } } command = client.RunCommand("docker ps|wc -l"); if (command.ExitStatus == 0) { serv.RunningContainerCount = int.Parse(command.Result); } command = client.RunCommand("docker inspect psc_web_1"); if (command.ExitStatus == 0) { JArray web = JArray.Parse(command.Result); var webEnvArray = web[0]["Config"]["Env"]; foreach (String entry in webEnvArray) { var webExploded = entry.Split("="); if (webExploded[0] == "LETSENCRYPT_HOST") { var webHosts = webExploded[1].Split(","); serv.Domains.Clear(); foreach (String dom in webHosts) { serv.Domains.Add(new Domain(dom)); } var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Accept.Clear(); httpClient.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/ld+json")); httpClient.DefaultRequestHeaders.Add("User-Agent", "PSC Client"); try { var stringTask = httpClient.GetStringAsync("https://" + webHosts[0] + "/apps/api/system/version"); var msg = await stringTask; JObject versionMSg = JObject.Parse(msg); serv.Datum = versionMSg["datum"].ToString(); serv.Release = float.Parse(versionMSg["release"].ToString()); } catch (Exception ex) { } } } } if (serv.PscApiKey != "" && serv.Domains.Count > 0) { var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Accept.Clear(); httpClient.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/ld+json")); httpClient.DefaultRequestHeaders.Add("User-Agent", "PSC Client"); httpClient.DefaultRequestHeaders.Add("apiKey", serv.PscApiKey); try { var stringPlugins = httpClient.GetStringAsync("https://" + serv.Domains.First().Name + "/apps/api/plugins"); var msg = await stringPlugins; JObject pluginMsg = JObject.Parse(msg); foreach (var plugin in pluginMsg["data"]) { serv.Plugins.Add(new Plugin() { Installed = bool.Parse(plugin["installed"].ToString()), Title = plugin["title"].ToString(), Uuid = plugin["uuid"].ToString() }); } } catch (Exception ex) { } } if (serv.PscApiKey != "" && serv.Domains.Count > 0) { var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Accept.Clear(); httpClient.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/ld+json")); httpClient.DefaultRequestHeaders.Add("User-Agent", "PSC Client"); httpClient.DefaultRequestHeaders.Add("apiKey", serv.PscApiKey); try { var stringPlugins = httpClient.GetStringAsync("https://" + serv.Domains.First().Name + "/apps/api/system/info"); var msg = await stringPlugins; JObject systemInfo = JObject.Parse(msg); serv.Instance.SftpUserName = systemInfo["sftpUserName"].ToString(); serv.Instance.SftpPassword = systemInfo["sftpPassword"].ToString(); serv.Instance.SftpHostName = systemInfo["sftpHost"].ToString(); serv.Instance.SmtpOwn = bool.Parse(systemInfo["smtpOwn"].ToString()); } catch (Exception ex) { } } serv.IsGoodIcon = MaterialIconKind.Check; serv.IsGoodColor = Brushes.Green; client.Disconnect(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } await uiDispatcher.InvokeAsync(() => { this._reloadTimer.Start(); }); } public void SaveSettings(Server selectedServer) { var settings = new Settings(); _settingsManager.LoadPluginSettings("HetznerSettings", settings); if (settings.ServerSettings.Count(e => e.ServerId == selectedServer.ServerId) > 0) { settings.ServerSettings.First(e => e.ServerId == selectedServer.ServerId).FastBillId = selectedServer.FastBillId; settings.ServerSettings.First(e => e.ServerId == selectedServer.ServerId).PscApiKey = selectedServer.PscApiKey; settings.ServerSettings.First(e => e.ServerId == selectedServer.ServerId).FastBillNr = selectedServer.FastBillNr; } else { settings.ServerSettings.Add(new ServerSetting(selectedServer.ServerId, selectedServer.PscApiKey, selectedServer.FastBillId, selectedServer.FastBillNr)); } _settingsManager.SavePluginSettings("HetznerSettings", settings); } }