add api to mare, change all to file scoped namespace
This commit is contained in:
2
MareAPI
2
MareAPI
Submodule MareAPI updated: 9dc1e901aa...57a7ab8262
@@ -7,8 +7,8 @@ using System.Linq;
|
|||||||
using MareSynchronos.Utils;
|
using MareSynchronos.Utils;
|
||||||
using MareSynchronos.WebAPI;
|
using MareSynchronos.WebAPI;
|
||||||
|
|
||||||
namespace MareSynchronos
|
namespace MareSynchronos;
|
||||||
{
|
|
||||||
public static class ConfigurationExtensions
|
public static class ConfigurationExtensions
|
||||||
{
|
{
|
||||||
public static bool HasValidSetup(this Configuration configuration)
|
public static bool HasValidSetup(this Configuration configuration)
|
||||||
@@ -198,4 +198,3 @@ namespace MareSynchronos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
|||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||||
using Penumbra.Interop.Structs;
|
using Penumbra.Interop.Structs;
|
||||||
|
|
||||||
namespace MareSynchronos.Interop
|
namespace MareSynchronos.Interop;
|
||||||
{
|
|
||||||
[StructLayout(LayoutKind.Explicit)]
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
public unsafe struct Weapon
|
public unsafe struct Weapon
|
||||||
{
|
{
|
||||||
@@ -35,4 +35,3 @@ namespace MareSynchronos.Interop
|
|||||||
[FieldOffset(0x0)] public Character Character;
|
[FieldOffset(0x0)] public Character Character;
|
||||||
[FieldOffset(0x650)] public Character* Mount;
|
[FieldOffset(0x650)] public Character* Mount;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using CheapLoc;
|
using CheapLoc;
|
||||||
|
|
||||||
namespace MareSynchronos.Localization
|
namespace MareSynchronos.Localization;
|
||||||
{
|
|
||||||
public static class Strings
|
public static class Strings
|
||||||
{
|
{
|
||||||
public class ToSStrings
|
public class ToSStrings
|
||||||
@@ -65,4 +65,3 @@ namespace MareSynchronos.Localization
|
|||||||
|
|
||||||
public static ToSStrings ToS { get; set; } = new();
|
public static ToSStrings ToS { get; set; } = new();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -8,8 +8,8 @@ using MareSynchronos.WebAPI;
|
|||||||
using Action = System.Action;
|
using Action = System.Action;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
namespace MareSynchronos.Managers
|
namespace MareSynchronos.Managers;
|
||||||
{
|
|
||||||
public delegate void PenumbraRedrawEvent(IntPtr address, int objTblIdx);
|
public delegate void PenumbraRedrawEvent(IntPtr address, int objTblIdx);
|
||||||
public delegate void HeelsOffsetChange(float change);
|
public delegate void HeelsOffsetChange(float change);
|
||||||
public delegate void PenumbraResourceLoadEvent(IntPtr drawObject, string gamePath, string filePath);
|
public delegate void PenumbraResourceLoadEvent(IntPtr drawObject, string gamePath, string filePath);
|
||||||
@@ -398,4 +398,3 @@ namespace MareSynchronos.Managers
|
|||||||
actionQueue.Clear();
|
actionQueue.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ using MareSynchronos.FileCache;
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace MareSynchronos.Managers
|
namespace MareSynchronos.Managers;
|
||||||
{
|
|
||||||
public delegate void PlayerHasChanged(CharacterCacheDto characterCache);
|
public delegate void PlayerHasChanged(CharacterCacheDto characterCache);
|
||||||
|
|
||||||
public class PlayerManager : IDisposable
|
public class PlayerManager : IDisposable
|
||||||
@@ -268,4 +268,3 @@ namespace MareSynchronos.Managers
|
|||||||
}, token);
|
}, token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MareSynchronos.Managers
|
namespace MareSynchronos.Managers;
|
||||||
{
|
|
||||||
public delegate void TransientResourceLoadedEvent(IntPtr drawObject);
|
public delegate void TransientResourceLoadedEvent(IntPtr drawObject);
|
||||||
|
|
||||||
public class TransientResourceManager : IDisposable
|
public class TransientResourceManager : IDisposable
|
||||||
@@ -202,4 +202,3 @@ namespace MareSynchronos.Managers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ using MareSynchronos.API;
|
|||||||
using MareSynchronos.Utils;
|
using MareSynchronos.Utils;
|
||||||
using Lumina.Excel.GeneratedSheets;
|
using Lumina.Excel.GeneratedSheets;
|
||||||
|
|
||||||
namespace MareSynchronos.Models
|
namespace MareSynchronos.Models;
|
||||||
{
|
|
||||||
[JsonObject(MemberSerialization.OptIn)]
|
[JsonObject(MemberSerialization.OptIn)]
|
||||||
public class CharacterData
|
public class CharacterData
|
||||||
{
|
{
|
||||||
@@ -85,4 +85,3 @@ namespace MareSynchronos.Models
|
|||||||
return stringBuilder.ToString();
|
return stringBuilder.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ using MareSynchronos.API;
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using MareSynchronos.FileCache;
|
using MareSynchronos.FileCache;
|
||||||
|
|
||||||
namespace MareSynchronos.Models
|
namespace MareSynchronos.Models;
|
||||||
{
|
|
||||||
public class FileReplacement
|
public class FileReplacement
|
||||||
{
|
{
|
||||||
private readonly FileCacheManager fileDbManager;
|
private readonly FileCacheManager fileDbManager;
|
||||||
@@ -57,4 +57,3 @@ namespace MareSynchronos.Models
|
|||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ using System.Runtime.InteropServices;
|
|||||||
using MareSynchronos.Utils;
|
using MareSynchronos.Utils;
|
||||||
using Penumbra.GameData.ByteString;
|
using Penumbra.GameData.ByteString;
|
||||||
|
|
||||||
namespace MareSynchronos.Models
|
namespace MareSynchronos.Models;
|
||||||
{
|
|
||||||
public class PlayerRelatedObject
|
public class PlayerRelatedObject
|
||||||
{
|
{
|
||||||
private readonly Func<IntPtr> getAddress;
|
private readonly Func<IntPtr> getAddress;
|
||||||
@@ -133,4 +133,3 @@ namespace MareSynchronos.Models
|
|||||||
return hasChanges;
|
return hasChanges;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ using MareSynchronos.Utils;
|
|||||||
using Dalamud.Game.ClientState.Conditions;
|
using Dalamud.Game.ClientState.Conditions;
|
||||||
using MareSynchronos.FileCache;
|
using MareSynchronos.FileCache;
|
||||||
|
|
||||||
namespace MareSynchronos
|
namespace MareSynchronos;
|
||||||
{
|
|
||||||
public sealed class Plugin : IDalamudPlugin
|
public sealed class Plugin : IDalamudPlugin
|
||||||
{
|
{
|
||||||
private const string CommandName = "/mare";
|
private const string CommandName = "/mare";
|
||||||
@@ -215,4 +215,3 @@ namespace MareSynchronos
|
|||||||
_introUi.Toggle();
|
_introUi.Toggle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ using MareSynchronos.API;
|
|||||||
using MareSynchronos.Utils;
|
using MareSynchronos.Utils;
|
||||||
using MareSynchronos.WebAPI;
|
using MareSynchronos.WebAPI;
|
||||||
|
|
||||||
namespace MareSynchronos.UI
|
namespace MareSynchronos.UI;
|
||||||
{
|
|
||||||
public class CompactUi : Window, IDisposable
|
public class CompactUi : Window, IDisposable
|
||||||
{
|
{
|
||||||
private readonly ApiController _apiController;
|
private readonly ApiController _apiController;
|
||||||
@@ -560,4 +560,3 @@ namespace MareSynchronos.UI
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ using MareSynchronos.Localization;
|
|||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using MareSynchronos.FileCache;
|
using MareSynchronos.FileCache;
|
||||||
|
|
||||||
namespace MareSynchronos.UI
|
namespace MareSynchronos.UI;
|
||||||
{
|
|
||||||
internal class IntroUi : Window, IDisposable
|
internal class IntroUi : Window, IDisposable
|
||||||
{
|
{
|
||||||
private readonly UiShared _uiShared;
|
private readonly UiShared _uiShared;
|
||||||
@@ -295,4 +295,3 @@ namespace MareSynchronos.UI
|
|||||||
return new($"{Strings.ToS.ParagraphLabel} {paragraphIdx + 1}, {Strings.ToS.SentenceLabel} {sentenceIdx + 1}, {Strings.ToS.WordLabel} {wordIdx + 1}", splitSentence[wordIdx]);
|
return new($"{Strings.ToS.ParagraphLabel} {paragraphIdx + 1}, {Strings.ToS.SentenceLabel} {sentenceIdx + 1}, {Strings.ToS.WordLabel} {wordIdx + 1}", splitSentence[wordIdx]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ using MareSynchronos.WebAPI.Utils;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
|
|
||||||
namespace MareSynchronos.UI
|
namespace MareSynchronos.UI;
|
||||||
{
|
|
||||||
public delegate void SwitchUi();
|
public delegate void SwitchUi();
|
||||||
public class SettingsUi : Window, IDisposable
|
public class SettingsUi : Window, IDisposable
|
||||||
{
|
{
|
||||||
@@ -610,4 +610,3 @@ namespace MareSynchronos.UI
|
|||||||
base.OnClose();
|
base.OnClose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ using MareSynchronos.Managers;
|
|||||||
using MareSynchronos.Utils;
|
using MareSynchronos.Utils;
|
||||||
using MareSynchronos.WebAPI;
|
using MareSynchronos.WebAPI;
|
||||||
|
|
||||||
namespace MareSynchronos.UI
|
namespace MareSynchronos.UI;
|
||||||
{
|
|
||||||
public class UiShared : IDisposable
|
public class UiShared : IDisposable
|
||||||
{
|
{
|
||||||
[DllImport("user32")]
|
[DllImport("user32")]
|
||||||
@@ -553,4 +553,3 @@ namespace MareSynchronos.UI
|
|||||||
_pluginInterface.UiBuilder.BuildFonts -= BuildFont;
|
_pluginInterface.UiBuilder.BuildFonts -= BuildFont;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ using System.Security.Cryptography;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||||
|
|
||||||
namespace MareSynchronos.Utils
|
namespace MareSynchronos.Utils;
|
||||||
{
|
|
||||||
public class Crypto
|
public class Crypto
|
||||||
{
|
{
|
||||||
public static string GetFileHash(string filePath)
|
public static string GetFileHash(string filePath)
|
||||||
@@ -32,4 +32,3 @@ namespace MareSynchronos.Utils
|
|||||||
return BitConverter.ToString(cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(character.Name + character.HomeWorld.Id.ToString()))).Replace("-", "");
|
return BitConverter.ToString(cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(character.Name + character.HomeWorld.Id.ToString()))).Replace("-", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ using Dalamud.Game.ClientState.Objects.SubKinds;
|
|||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
using GameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject;
|
using GameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject;
|
||||||
|
|
||||||
namespace MareSynchronos.Utils
|
namespace MareSynchronos.Utils;
|
||||||
{
|
|
||||||
public delegate void PlayerChange(Dalamud.Game.ClientState.Objects.Types.Character actor);
|
public delegate void PlayerChange(Dalamud.Game.ClientState.Objects.Types.Character actor);
|
||||||
|
|
||||||
public delegate void LogIn();
|
public delegate void LogIn();
|
||||||
@@ -239,4 +239,3 @@ namespace MareSynchronos.Utils
|
|||||||
_framework.Update -= FrameworkOnUpdate;
|
_framework.Update -= FrameworkOnUpdate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ using Dalamud.Logging;
|
|||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace MareSynchronos.Utils
|
namespace MareSynchronos.Utils;
|
||||||
{
|
|
||||||
[ProviderAlias("Dalamud")]
|
[ProviderAlias("Dalamud")]
|
||||||
public class DalamudLoggingProvider : ILoggerProvider
|
public class DalamudLoggingProvider : ILoggerProvider
|
||||||
{
|
{
|
||||||
@@ -109,4 +109,3 @@ namespace MareSynchronos.Utils
|
|||||||
|
|
||||||
public IDisposable BeginScope<TState>(TState state) => default!;
|
public IDisposable BeginScope<TState>(TState state) => default!;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ using System.Reflection;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MareSynchronos.Utils
|
namespace MareSynchronos.Utils;
|
||||||
{
|
|
||||||
public static class VariousExtensions
|
public static class VariousExtensions
|
||||||
{
|
{
|
||||||
public static DateTime GetLinkerTime(Assembly assembly)
|
public static DateTime GetLinkerTime(Assembly assembly)
|
||||||
@@ -29,4 +29,3 @@ namespace MareSynchronos.Utils
|
|||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ using MareSynchronos.Utils;
|
|||||||
using MareSynchronos.WebAPI.Utils;
|
using MareSynchronos.WebAPI.Utils;
|
||||||
using Microsoft.AspNetCore.SignalR.Client;
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
|
||||||
namespace MareSynchronos.WebAPI
|
namespace MareSynchronos.WebAPI;
|
||||||
{
|
|
||||||
public partial class ApiController
|
public partial class ApiController
|
||||||
{
|
{
|
||||||
private readonly HashSet<string> _verifiedUploadedHashes;
|
private readonly HashSet<string> _verifiedUploadedHashes;
|
||||||
@@ -315,4 +315,3 @@ namespace MareSynchronos.WebAPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MareSynchronos.API;
|
using MareSynchronos.API;
|
||||||
using MareSynchronos.Utils;
|
|
||||||
using Microsoft.AspNetCore.SignalR.Client;
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
|
||||||
namespace MareSynchronos.WebAPI
|
namespace MareSynchronos.WebAPI;
|
||||||
{
|
|
||||||
public partial class ApiController
|
public partial class ApiController
|
||||||
{
|
{
|
||||||
public async Task DeleteAccount()
|
public async Task DeleteAccount()
|
||||||
@@ -41,4 +40,4 @@ namespace MareSynchronos.WebAPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,372 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MareSynchronos.API;
|
|
||||||
using MareSynchronos.FileCache;
|
|
||||||
using MareSynchronos.Utils;
|
|
||||||
using MareSynchronos.WebAPI.Utils;
|
|
||||||
using Microsoft.AspNetCore.Http.Connections;
|
|
||||||
using Microsoft.AspNetCore.SignalR;
|
|
||||||
using Microsoft.AspNetCore.SignalR.Client;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace MareSynchronos.WebAPI
|
|
||||||
{
|
|
||||||
public delegate void SimpleStringDelegate(string str);
|
|
||||||
public enum ServerState
|
|
||||||
{
|
|
||||||
Offline,
|
|
||||||
Disconnected,
|
|
||||||
Connected,
|
|
||||||
Unauthorized,
|
|
||||||
VersionMisMatch,
|
|
||||||
RateLimited
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial class ApiController : IDisposable
|
|
||||||
{
|
|
||||||
public const string MainServer = "Lunae Crescere Incipientis (Central Server EU)";
|
|
||||||
public const string MainServiceUri = "wss://maresynchronos.com";
|
|
||||||
|
|
||||||
public readonly int[] SupportedServerVersions = { Api.Version };
|
|
||||||
|
|
||||||
private readonly Configuration _pluginConfiguration;
|
|
||||||
private readonly DalamudUtil _dalamudUtil;
|
|
||||||
private readonly FileCacheManager _fileDbManager;
|
|
||||||
private CancellationTokenSource _connectionCancellationTokenSource;
|
|
||||||
|
|
||||||
private HubConnection? _mareHub;
|
|
||||||
|
|
||||||
private CancellationTokenSource? _uploadCancellationTokenSource = new();
|
|
||||||
|
|
||||||
private ConnectionDto? _connectionDto;
|
|
||||||
public SystemInfoDto SystemInfoDto { get; private set; } = new();
|
|
||||||
public bool IsModerator => (_connectionDto?.IsAdmin ?? false) || (_connectionDto?.IsModerator ?? false);
|
|
||||||
|
|
||||||
public bool IsAdmin => _connectionDto?.IsAdmin ?? false;
|
|
||||||
|
|
||||||
public ApiController(Configuration pluginConfiguration, DalamudUtil dalamudUtil, FileCacheManager fileDbManager)
|
|
||||||
{
|
|
||||||
Logger.Verbose("Creating " + nameof(ApiController));
|
|
||||||
|
|
||||||
_pluginConfiguration = pluginConfiguration;
|
|
||||||
_dalamudUtil = dalamudUtil;
|
|
||||||
_fileDbManager = fileDbManager;
|
|
||||||
_connectionCancellationTokenSource = new CancellationTokenSource();
|
|
||||||
_dalamudUtil.LogIn += DalamudUtilOnLogIn;
|
|
||||||
_dalamudUtil.LogOut += DalamudUtilOnLogOut;
|
|
||||||
ServerState = ServerState.Offline;
|
|
||||||
_verifiedUploadedHashes = new();
|
|
||||||
|
|
||||||
if (_dalamudUtil.IsLoggedIn)
|
|
||||||
{
|
|
||||||
DalamudUtilOnLogIn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DalamudUtilOnLogOut()
|
|
||||||
{
|
|
||||||
Task.Run(async () => await StopConnection(_connectionCancellationTokenSource.Token));
|
|
||||||
ServerState = ServerState.Offline;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DalamudUtilOnLogIn()
|
|
||||||
{
|
|
||||||
Task.Run(CreateConnections);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public event EventHandler<CharacterReceivedEventArgs>? CharacterReceived;
|
|
||||||
|
|
||||||
public event VoidDelegate? Connected;
|
|
||||||
|
|
||||||
public event VoidDelegate? Disconnected;
|
|
||||||
|
|
||||||
public event SimpleStringDelegate? PairedClientOffline;
|
|
||||||
|
|
||||||
public event SimpleStringDelegate? PairedClientOnline;
|
|
||||||
|
|
||||||
public event SimpleStringDelegate? PairedWithOther;
|
|
||||||
|
|
||||||
public event SimpleStringDelegate? UnpairedFromOther;
|
|
||||||
public event VoidDelegate? DownloadStarted;
|
|
||||||
public event VoidDelegate? DownloadFinished;
|
|
||||||
|
|
||||||
public ConcurrentDictionary<int, List<DownloadFileTransfer>> CurrentDownloads { get; } = new();
|
|
||||||
|
|
||||||
public List<FileTransfer> CurrentUploads { get; } = new();
|
|
||||||
|
|
||||||
public List<FileTransfer> ForbiddenTransfers { get; } = new();
|
|
||||||
|
|
||||||
public List<BannedUserDto> AdminBannedUsers { get; private set; } = new();
|
|
||||||
|
|
||||||
public List<ForbiddenFileDto> AdminForbiddenFiles { get; private set; } = new();
|
|
||||||
|
|
||||||
public bool IsConnected => ServerState == ServerState.Connected;
|
|
||||||
|
|
||||||
public bool IsDownloading => CurrentDownloads.Count > 0;
|
|
||||||
|
|
||||||
public bool IsUploading => CurrentUploads.Count > 0;
|
|
||||||
|
|
||||||
public List<ClientPairDto> PairedClients { get; set; } = new();
|
|
||||||
|
|
||||||
public string SecretKey => _pluginConfiguration.ClientSecret.ContainsKey(ApiUri)
|
|
||||||
? _pluginConfiguration.ClientSecret[ApiUri] : string.Empty;
|
|
||||||
|
|
||||||
public bool ServerAlive => ServerState is ServerState.Connected or ServerState.RateLimited or ServerState.Unauthorized or ServerState.Disconnected;
|
|
||||||
|
|
||||||
public Dictionary<string, string> ServerDictionary => new Dictionary<string, string>()
|
|
||||||
{ { MainServiceUri, MainServer } }
|
|
||||||
.Concat(_pluginConfiguration.CustomServerList)
|
|
||||||
.ToDictionary(k => k.Key, k => k.Value);
|
|
||||||
|
|
||||||
public string UID => _connectionDto?.UID ?? string.Empty;
|
|
||||||
private string ApiUri => _pluginConfiguration.ApiUri;
|
|
||||||
public int OnlineUsers => SystemInfoDto.OnlineUsers;
|
|
||||||
|
|
||||||
private ServerState _serverState;
|
|
||||||
public ServerState ServerState
|
|
||||||
{
|
|
||||||
get => _serverState;
|
|
||||||
private set
|
|
||||||
{
|
|
||||||
Logger.Debug($"New ServerState: {value}, prev ServerState: {_serverState}");
|
|
||||||
_serverState = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task CreateConnections()
|
|
||||||
{
|
|
||||||
Logger.Debug("CreateConnections called");
|
|
||||||
|
|
||||||
if (_pluginConfiguration.FullPause)
|
|
||||||
{
|
|
||||||
Logger.Info("Not recreating Connection, paused");
|
|
||||||
ServerState = ServerState.Disconnected;
|
|
||||||
_connectionDto = null;
|
|
||||||
await StopConnection(_connectionCancellationTokenSource.Token);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await StopConnection(_connectionCancellationTokenSource.Token);
|
|
||||||
|
|
||||||
Logger.Info("Recreating Connection");
|
|
||||||
|
|
||||||
_connectionCancellationTokenSource.Cancel();
|
|
||||||
_connectionCancellationTokenSource = new CancellationTokenSource();
|
|
||||||
var token = _connectionCancellationTokenSource.Token;
|
|
||||||
_verifiedUploadedHashes.Clear();
|
|
||||||
while (ServerState is not ServerState.Connected && !token.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(SecretKey))
|
|
||||||
{
|
|
||||||
await Task.Delay(TimeSpan.FromSeconds(2));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
await StopConnection(token);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Logger.Debug("Building connection");
|
|
||||||
|
|
||||||
while (!_dalamudUtil.IsPlayerPresent && !token.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
Logger.Debug("Player not loaded in yet, waiting");
|
|
||||||
await Task.Delay(TimeSpan.FromSeconds(1), token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token.IsCancellationRequested) break;
|
|
||||||
|
|
||||||
_mareHub = BuildHubConnection(Api.Path);
|
|
||||||
|
|
||||||
await _mareHub.StartAsync(token);
|
|
||||||
|
|
||||||
_mareHub.On<SystemInfoDto>(Api.OnUpdateSystemInfo, (dto) => SystemInfoDto = dto);
|
|
||||||
|
|
||||||
_connectionDto =
|
|
||||||
await _mareHub.InvokeAsync<ConnectionDto>(Api.InvokeHeartbeat, _dalamudUtil.PlayerNameHashed, token);
|
|
||||||
|
|
||||||
ServerState = ServerState.Connected;
|
|
||||||
|
|
||||||
if (_connectionDto.ServerVersion != Api.Version)
|
|
||||||
{
|
|
||||||
ServerState = ServerState.VersionMisMatch;
|
|
||||||
await StopConnection(token);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ServerState is ServerState.Connected) // user is authorized && server is legit
|
|
||||||
{
|
|
||||||
await InitializeData(token);
|
|
||||||
|
|
||||||
_mareHub.Closed += MareHubOnClosed;
|
|
||||||
_mareHub.Reconnecting += MareHubOnReconnecting;
|
|
||||||
_mareHub.Reconnected += MareHubOnReconnected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (HubException ex)
|
|
||||||
{
|
|
||||||
Logger.Warn(ex.GetType().ToString());
|
|
||||||
Logger.Warn(ex.Message);
|
|
||||||
Logger.Warn(ex.StackTrace ?? string.Empty);
|
|
||||||
|
|
||||||
ServerState = ServerState.RateLimited;
|
|
||||||
await StopConnection(token);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (HttpRequestException ex)
|
|
||||||
{
|
|
||||||
Logger.Warn(ex.GetType().ToString());
|
|
||||||
Logger.Warn(ex.Message);
|
|
||||||
Logger.Warn(ex.StackTrace ?? string.Empty);
|
|
||||||
|
|
||||||
if (ex.StatusCode == System.Net.HttpStatusCode.Unauthorized)
|
|
||||||
{
|
|
||||||
ServerState = ServerState.Unauthorized;
|
|
||||||
await StopConnection(token);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ServerState = ServerState.Offline;
|
|
||||||
Logger.Info("Failed to establish connection, retrying");
|
|
||||||
await Task.Delay(TimeSpan.FromSeconds(new Random().Next(5, 20)), token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.Warn(ex.GetType().ToString());
|
|
||||||
Logger.Warn(ex.Message);
|
|
||||||
Logger.Warn(ex.StackTrace ?? string.Empty);
|
|
||||||
Logger.Info("Failed to establish connection, retrying");
|
|
||||||
await Task.Delay(TimeSpan.FromSeconds(new Random().Next(5, 20)), token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task MareHubOnReconnected(string? arg)
|
|
||||||
{
|
|
||||||
_ = Task.Run(CreateConnections);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task InitializeData(CancellationToken token)
|
|
||||||
{
|
|
||||||
if (_mareHub == null) return;
|
|
||||||
|
|
||||||
Logger.Debug("Initializing data");
|
|
||||||
_mareHub.On<ClientPairDto, string>(Api.OnUserUpdateClientPairs,
|
|
||||||
UpdateLocalClientPairsCallback);
|
|
||||||
_mareHub.On<CharacterCacheDto, string>(Api.OnUserReceiveCharacterData,
|
|
||||||
ReceiveCharacterDataCallback);
|
|
||||||
_mareHub.On<string>(Api.OnUserRemoveOnlinePairedPlayer,
|
|
||||||
(s) => PairedClientOffline?.Invoke(s));
|
|
||||||
_mareHub.On<string>(Api.OnUserAddOnlinePairedPlayer,
|
|
||||||
(s) => PairedClientOnline?.Invoke(s));
|
|
||||||
_mareHub.On(Api.OnAdminForcedReconnect, UserForcedReconnectCallback);
|
|
||||||
|
|
||||||
PairedClients =
|
|
||||||
await _mareHub!.InvokeAsync<List<ClientPairDto>>(Api.InvokeUserGetPairedClients, token);
|
|
||||||
|
|
||||||
if (IsModerator)
|
|
||||||
{
|
|
||||||
AdminForbiddenFiles =
|
|
||||||
await _mareHub.InvokeAsync<List<ForbiddenFileDto>>(Api.InvokeAdminGetForbiddenFiles,
|
|
||||||
token);
|
|
||||||
AdminBannedUsers =
|
|
||||||
await _mareHub.InvokeAsync<List<BannedUserDto>>(Api.InvokeAdminGetBannedUsers,
|
|
||||||
token);
|
|
||||||
_mareHub.On<BannedUserDto>(Api.OnAdminUpdateOrAddBannedUser,
|
|
||||||
UpdateOrAddBannedUserCallback);
|
|
||||||
_mareHub.On<BannedUserDto>(Api.OnAdminDeleteBannedUser, DeleteBannedUserCallback);
|
|
||||||
_mareHub.On<ForbiddenFileDto>(Api.OnAdminUpdateOrAddForbiddenFile,
|
|
||||||
UpdateOrAddForbiddenFileCallback);
|
|
||||||
_mareHub.On<ForbiddenFileDto>(Api.OnAdminDeleteForbiddenFile,
|
|
||||||
DeleteForbiddenFileCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
Connected?.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Logger.Verbose("Disposing " + nameof(ApiController));
|
|
||||||
|
|
||||||
_dalamudUtil.LogIn -= DalamudUtilOnLogIn;
|
|
||||||
_dalamudUtil.LogOut -= DalamudUtilOnLogOut;
|
|
||||||
|
|
||||||
Task.Run(async () => await StopConnection(_connectionCancellationTokenSource.Token));
|
|
||||||
_connectionCancellationTokenSource?.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private HubConnection BuildHubConnection(string hubName)
|
|
||||||
{
|
|
||||||
return new HubConnectionBuilder()
|
|
||||||
.WithUrl(ApiUri + hubName, options =>
|
|
||||||
{
|
|
||||||
options.Headers.Add("Authorization", SecretKey);
|
|
||||||
options.Transports = HttpTransportType.WebSockets | HttpTransportType.ServerSentEvents | HttpTransportType.LongPolling;
|
|
||||||
})
|
|
||||||
.WithAutomaticReconnect(new ForeverRetryPolicy())
|
|
||||||
.ConfigureLogging(a => {
|
|
||||||
a.ClearProviders().AddProvider(new DalamudLoggingProvider());
|
|
||||||
a.SetMinimumLevel(LogLevel.Warning);
|
|
||||||
})
|
|
||||||
.Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task MareHubOnClosed(Exception? arg)
|
|
||||||
{
|
|
||||||
CurrentUploads.Clear();
|
|
||||||
CurrentDownloads.Clear();
|
|
||||||
_uploadCancellationTokenSource?.Cancel();
|
|
||||||
Disconnected?.Invoke();
|
|
||||||
ServerState = ServerState.Offline;
|
|
||||||
Logger.Info("Connection closed");
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task MareHubOnReconnecting(Exception? arg)
|
|
||||||
{
|
|
||||||
ServerState = ServerState.Disconnected;
|
|
||||||
Logger.Warn("Connection closed... Reconnecting");
|
|
||||||
Logger.Warn(arg?.Message ?? string.Empty);
|
|
||||||
Logger.Warn(arg?.StackTrace ?? string.Empty);
|
|
||||||
Disconnected?.Invoke();
|
|
||||||
ServerState = ServerState.Offline;
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task StopConnection(CancellationToken token)
|
|
||||||
{
|
|
||||||
if (_mareHub is not null)
|
|
||||||
{
|
|
||||||
_uploadCancellationTokenSource?.Cancel();
|
|
||||||
Logger.Info("Stopping existing connection");
|
|
||||||
_mareHub.Closed -= MareHubOnClosed;
|
|
||||||
_mareHub.Reconnecting -= MareHubOnReconnecting;
|
|
||||||
_mareHub.Reconnected -= MareHubOnReconnected;
|
|
||||||
await _mareHub.StopAsync(token);
|
|
||||||
await _mareHub.DisposeAsync();
|
|
||||||
CurrentUploads.Clear();
|
|
||||||
CurrentDownloads.Clear();
|
|
||||||
_uploadCancellationTokenSource?.Cancel();
|
|
||||||
Disconnected?.Invoke();
|
|
||||||
_mareHub = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ServerState != ServerState.Disconnected)
|
|
||||||
{
|
|
||||||
while (ServerState != ServerState.Offline)
|
|
||||||
{
|
|
||||||
await Task.Delay(16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,8 +3,8 @@ using System.Threading.Tasks;
|
|||||||
using MareSynchronos.API;
|
using MareSynchronos.API;
|
||||||
using Microsoft.AspNetCore.SignalR.Client;
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
|
||||||
namespace MareSynchronos.WebAPI
|
namespace MareSynchronos.WebAPI;
|
||||||
{
|
|
||||||
public partial class ApiController
|
public partial class ApiController
|
||||||
{
|
{
|
||||||
public async Task AddOrUpdateForbiddenFileEntry(ForbiddenFileDto forbiddenFile)
|
public async Task AddOrUpdateForbiddenFileEntry(ForbiddenFileDto forbiddenFile)
|
||||||
@@ -44,4 +44,3 @@ namespace MareSynchronos.WebAPI
|
|||||||
_mareHub!.SendAsync(Api.SendAdminChangeModeratorStatus, onlineUserUID, false);
|
_mareHub!.SendAsync(Api.SendAdminChangeModeratorStatus, onlineUserUID, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ using MareSynchronos.API;
|
|||||||
using MareSynchronos.Utils;
|
using MareSynchronos.Utils;
|
||||||
using MareSynchronos.WebAPI.Utils;
|
using MareSynchronos.WebAPI.Utils;
|
||||||
|
|
||||||
namespace MareSynchronos.WebAPI
|
namespace MareSynchronos.WebAPI;
|
||||||
{
|
|
||||||
public partial class ApiController
|
public partial class ApiController
|
||||||
{
|
{
|
||||||
private void UserForcedReconnectCallback()
|
private void UserForcedReconnectCallback()
|
||||||
@@ -74,5 +74,14 @@ namespace MareSynchronos.WebAPI
|
|||||||
{
|
{
|
||||||
AdminForbiddenFiles.RemoveAll(f => f.Hash == obj.Hash);
|
AdminForbiddenFiles.RemoveAll(f => f.Hash == obj.Hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GroupPairChangedCallback(GroupPairDto dto)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GroupChangedCallback(GroupDto dto)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
64
MareSynchronos/WebAPI/ApiController.Functions.Groups.cs
Normal file
64
MareSynchronos/WebAPI/ApiController.Functions.Groups.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
using MareSynchronos.API;
|
||||||
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MareSynchronos.WebAPI;
|
||||||
|
public partial class ApiController
|
||||||
|
{
|
||||||
|
public async Task<GroupCreatedDto> CreateGroup()
|
||||||
|
{
|
||||||
|
return await _mareHub!.InvokeAsync<GroupCreatedDto>(Api.InvokeGroupCreate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> ChangeGroupPassword(string gid, string newpassword)
|
||||||
|
{
|
||||||
|
return await _mareHub!.InvokeAsync<bool>(Api.InvokeGroupChangePassword, gid, newpassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<GroupDto>> GetGroups()
|
||||||
|
{
|
||||||
|
return await _mareHub!.InvokeAsync<List<GroupDto>>(Api.InvokeGroupGetGroups);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<GroupPairDto>> GetUsersInGroup(string gid)
|
||||||
|
{
|
||||||
|
return await _mareHub!.InvokeAsync<List<GroupPairDto>>(Api.InvokeGroupGetUsersInGroup, gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendGroupJoin(string gid, string password)
|
||||||
|
{
|
||||||
|
if (!IsConnected || SecretKey == "-") return;
|
||||||
|
await _mareHub!.SendAsync(Api.SendGroupJoin, gid, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendGroupChangeInviteState(string gid, bool opened)
|
||||||
|
{
|
||||||
|
await _mareHub!.SendAsync(Api.SendGroupChangeInviteState, gid, opened);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendDeleteGroup(string gid)
|
||||||
|
{
|
||||||
|
await _mareHub!.SendAsync(Api.SendGroupDelete, gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendLeaveGroup(string gid)
|
||||||
|
{
|
||||||
|
await _mareHub!.SendAsync(Api.SendGroupLeave, gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendPauseGroup(string gid, bool isPaused)
|
||||||
|
{
|
||||||
|
await _mareHub!.SendAsync(Api.SendGroupPause, gid, isPaused);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendRemoveUserFromGroup(string gid, string uid)
|
||||||
|
{
|
||||||
|
await _mareHub!.SendAsync(Api.SendGroupRemoveUser, gid, uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ChangeOwnerOfGroup(string gid, string uid)
|
||||||
|
{
|
||||||
|
await _mareHub!.SendAsync(Api.SendGroupChangeOwner, gid, uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
372
MareSynchronos/WebAPI/ApiController.cs
Normal file
372
MareSynchronos/WebAPI/ApiController.cs
Normal file
@@ -0,0 +1,372 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MareSynchronos.API;
|
||||||
|
using MareSynchronos.FileCache;
|
||||||
|
using MareSynchronos.Utils;
|
||||||
|
using MareSynchronos.WebAPI.Utils;
|
||||||
|
using Microsoft.AspNetCore.Http.Connections;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace MareSynchronos.WebAPI;
|
||||||
|
|
||||||
|
public delegate void SimpleStringDelegate(string str);
|
||||||
|
|
||||||
|
public partial class ApiController : IDisposable
|
||||||
|
{
|
||||||
|
public const string MainServer = "Lunae Crescere Incipientis (Central Server EU)";
|
||||||
|
public const string MainServiceUri = "wss://maresynchronos.com";
|
||||||
|
|
||||||
|
public readonly int[] SupportedServerVersions = { Api.Version };
|
||||||
|
|
||||||
|
private readonly Configuration _pluginConfiguration;
|
||||||
|
private readonly DalamudUtil _dalamudUtil;
|
||||||
|
private readonly FileCacheManager _fileDbManager;
|
||||||
|
private CancellationTokenSource _connectionCancellationTokenSource;
|
||||||
|
|
||||||
|
private HubConnection? _mareHub;
|
||||||
|
|
||||||
|
private CancellationTokenSource? _uploadCancellationTokenSource = new();
|
||||||
|
|
||||||
|
private ConnectionDto? _connectionDto;
|
||||||
|
public SystemInfoDto SystemInfoDto { get; private set; } = new();
|
||||||
|
public bool IsModerator => (_connectionDto?.IsAdmin ?? false) || (_connectionDto?.IsModerator ?? false);
|
||||||
|
|
||||||
|
public bool IsAdmin => _connectionDto?.IsAdmin ?? false;
|
||||||
|
|
||||||
|
public ApiController(Configuration pluginConfiguration, DalamudUtil dalamudUtil, FileCacheManager fileDbManager)
|
||||||
|
{
|
||||||
|
Logger.Verbose("Creating " + nameof(ApiController));
|
||||||
|
|
||||||
|
_pluginConfiguration = pluginConfiguration;
|
||||||
|
_dalamudUtil = dalamudUtil;
|
||||||
|
_fileDbManager = fileDbManager;
|
||||||
|
_connectionCancellationTokenSource = new CancellationTokenSource();
|
||||||
|
_dalamudUtil.LogIn += DalamudUtilOnLogIn;
|
||||||
|
_dalamudUtil.LogOut += DalamudUtilOnLogOut;
|
||||||
|
ServerState = ServerState.Offline;
|
||||||
|
_verifiedUploadedHashes = new();
|
||||||
|
|
||||||
|
if (_dalamudUtil.IsLoggedIn)
|
||||||
|
{
|
||||||
|
DalamudUtilOnLogIn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DalamudUtilOnLogOut()
|
||||||
|
{
|
||||||
|
Task.Run(async () => await StopConnection(_connectionCancellationTokenSource.Token));
|
||||||
|
ServerState = ServerState.Offline;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DalamudUtilOnLogIn()
|
||||||
|
{
|
||||||
|
Task.Run(CreateConnections);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public event EventHandler<CharacterReceivedEventArgs>? CharacterReceived;
|
||||||
|
|
||||||
|
public event VoidDelegate? Connected;
|
||||||
|
|
||||||
|
public event VoidDelegate? Disconnected;
|
||||||
|
|
||||||
|
public event SimpleStringDelegate? PairedClientOffline;
|
||||||
|
|
||||||
|
public event SimpleStringDelegate? PairedClientOnline;
|
||||||
|
|
||||||
|
public event SimpleStringDelegate? PairedWithOther;
|
||||||
|
|
||||||
|
public event SimpleStringDelegate? UnpairedFromOther;
|
||||||
|
public event VoidDelegate? DownloadStarted;
|
||||||
|
public event VoidDelegate? DownloadFinished;
|
||||||
|
|
||||||
|
public ConcurrentDictionary<int, List<DownloadFileTransfer>> CurrentDownloads { get; } = new();
|
||||||
|
|
||||||
|
public List<FileTransfer> CurrentUploads { get; } = new();
|
||||||
|
|
||||||
|
public List<FileTransfer> ForbiddenTransfers { get; } = new();
|
||||||
|
|
||||||
|
public List<BannedUserDto> AdminBannedUsers { get; private set; } = new();
|
||||||
|
|
||||||
|
public List<ForbiddenFileDto> AdminForbiddenFiles { get; private set; } = new();
|
||||||
|
|
||||||
|
public bool IsConnected => ServerState == ServerState.Connected;
|
||||||
|
|
||||||
|
public bool IsDownloading => CurrentDownloads.Count > 0;
|
||||||
|
|
||||||
|
public bool IsUploading => CurrentUploads.Count > 0;
|
||||||
|
|
||||||
|
public List<ClientPairDto> PairedClients { get; set; } = new();
|
||||||
|
public List<GroupPairDto> GroupPairedClients { get; set; } = new();
|
||||||
|
public List<GroupDto> Groups { get; set; } = new();
|
||||||
|
|
||||||
|
public string SecretKey => _pluginConfiguration.ClientSecret.ContainsKey(ApiUri)
|
||||||
|
? _pluginConfiguration.ClientSecret[ApiUri] : string.Empty;
|
||||||
|
|
||||||
|
public bool ServerAlive => ServerState is ServerState.Connected or ServerState.RateLimited or ServerState.Unauthorized or ServerState.Disconnected;
|
||||||
|
|
||||||
|
public Dictionary<string, string> ServerDictionary => new Dictionary<string, string>()
|
||||||
|
{ { MainServiceUri, MainServer } }
|
||||||
|
.Concat(_pluginConfiguration.CustomServerList)
|
||||||
|
.ToDictionary(k => k.Key, k => k.Value);
|
||||||
|
|
||||||
|
public string UID => _connectionDto?.UID ?? string.Empty;
|
||||||
|
private string ApiUri => _pluginConfiguration.ApiUri;
|
||||||
|
public int OnlineUsers => SystemInfoDto.OnlineUsers;
|
||||||
|
|
||||||
|
private ServerState _serverState;
|
||||||
|
public ServerState ServerState
|
||||||
|
{
|
||||||
|
get => _serverState;
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
Logger.Debug($"New ServerState: {value}, prev ServerState: {_serverState}");
|
||||||
|
_serverState = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task CreateConnections()
|
||||||
|
{
|
||||||
|
Logger.Debug("CreateConnections called");
|
||||||
|
|
||||||
|
if (_pluginConfiguration.FullPause)
|
||||||
|
{
|
||||||
|
Logger.Info("Not recreating Connection, paused");
|
||||||
|
ServerState = ServerState.Disconnected;
|
||||||
|
_connectionDto = null;
|
||||||
|
await StopConnection(_connectionCancellationTokenSource.Token);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await StopConnection(_connectionCancellationTokenSource.Token);
|
||||||
|
|
||||||
|
Logger.Info("Recreating Connection");
|
||||||
|
|
||||||
|
_connectionCancellationTokenSource.Cancel();
|
||||||
|
_connectionCancellationTokenSource = new CancellationTokenSource();
|
||||||
|
var token = _connectionCancellationTokenSource.Token;
|
||||||
|
_verifiedUploadedHashes.Clear();
|
||||||
|
while (ServerState is not ServerState.Connected && !token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(SecretKey))
|
||||||
|
{
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(2));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
await StopConnection(token);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Logger.Debug("Building connection");
|
||||||
|
|
||||||
|
while (!_dalamudUtil.IsPlayerPresent && !token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
Logger.Debug("Player not loaded in yet, waiting");
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(1), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token.IsCancellationRequested) break;
|
||||||
|
|
||||||
|
_mareHub = BuildHubConnection(Api.Path);
|
||||||
|
|
||||||
|
await _mareHub.StartAsync(token);
|
||||||
|
|
||||||
|
_mareHub.On<SystemInfoDto>(Api.OnUpdateSystemInfo, (dto) => SystemInfoDto = dto);
|
||||||
|
|
||||||
|
_connectionDto =
|
||||||
|
await _mareHub.InvokeAsync<ConnectionDto>(Api.InvokeHeartbeat, _dalamudUtil.PlayerNameHashed, token);
|
||||||
|
|
||||||
|
ServerState = ServerState.Connected;
|
||||||
|
|
||||||
|
if (_connectionDto.ServerVersion != Api.Version)
|
||||||
|
{
|
||||||
|
ServerState = ServerState.VersionMisMatch;
|
||||||
|
await StopConnection(token);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ServerState is ServerState.Connected) // user is authorized && server is legit
|
||||||
|
{
|
||||||
|
await InitializeData(token);
|
||||||
|
|
||||||
|
_mareHub.Closed += MareHubOnClosed;
|
||||||
|
_mareHub.Reconnecting += MareHubOnReconnecting;
|
||||||
|
_mareHub.Reconnected += MareHubOnReconnected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (HubException ex)
|
||||||
|
{
|
||||||
|
Logger.Warn(ex.GetType().ToString());
|
||||||
|
Logger.Warn(ex.Message);
|
||||||
|
Logger.Warn(ex.StackTrace ?? string.Empty);
|
||||||
|
|
||||||
|
ServerState = ServerState.RateLimited;
|
||||||
|
await StopConnection(token);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
Logger.Warn(ex.GetType().ToString());
|
||||||
|
Logger.Warn(ex.Message);
|
||||||
|
Logger.Warn(ex.StackTrace ?? string.Empty);
|
||||||
|
|
||||||
|
if (ex.StatusCode == System.Net.HttpStatusCode.Unauthorized)
|
||||||
|
{
|
||||||
|
ServerState = ServerState.Unauthorized;
|
||||||
|
await StopConnection(token);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ServerState = ServerState.Offline;
|
||||||
|
Logger.Info("Failed to establish connection, retrying");
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(new Random().Next(5, 20)), token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Warn(ex.GetType().ToString());
|
||||||
|
Logger.Warn(ex.Message);
|
||||||
|
Logger.Warn(ex.StackTrace ?? string.Empty);
|
||||||
|
Logger.Info("Failed to establish connection, retrying");
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(new Random().Next(5, 20)), token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task MareHubOnReconnected(string? arg)
|
||||||
|
{
|
||||||
|
_ = Task.Run(CreateConnections);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InitializeData(CancellationToken token)
|
||||||
|
{
|
||||||
|
if (_mareHub == null) return;
|
||||||
|
|
||||||
|
Logger.Debug("Initializing data");
|
||||||
|
_mareHub.On<ClientPairDto>(Api.OnUserUpdateClientPairs,
|
||||||
|
UpdateLocalClientPairsCallback);
|
||||||
|
_mareHub.On<CharacterCacheDto, string>(Api.OnUserReceiveCharacterData,
|
||||||
|
ReceiveCharacterDataCallback);
|
||||||
|
_mareHub.On<string>(Api.OnUserRemoveOnlinePairedPlayer,
|
||||||
|
(s) => PairedClientOffline?.Invoke(s));
|
||||||
|
_mareHub.On<string>(Api.OnUserAddOnlinePairedPlayer,
|
||||||
|
(s) => PairedClientOnline?.Invoke(s));
|
||||||
|
_mareHub.On(Api.OnAdminForcedReconnect, UserForcedReconnectCallback);
|
||||||
|
_mareHub.On<GroupDto>(Api.OnGroupChange, GroupChangedCallback);
|
||||||
|
_mareHub.On<GroupPairDto>(Api.OnGroupUserChange, GroupPairChangedCallback);
|
||||||
|
|
||||||
|
PairedClients =
|
||||||
|
await _mareHub!.InvokeAsync<List<ClientPairDto>>(Api.InvokeUserGetPairedClients, token);
|
||||||
|
Groups = await GetGroups();
|
||||||
|
foreach (var group in Groups)
|
||||||
|
{
|
||||||
|
GroupPairedClients.AddRange(await GetUsersInGroup(group.GID));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsModerator)
|
||||||
|
{
|
||||||
|
AdminForbiddenFiles =
|
||||||
|
await _mareHub.InvokeAsync<List<ForbiddenFileDto>>(Api.InvokeAdminGetForbiddenFiles,
|
||||||
|
token);
|
||||||
|
AdminBannedUsers =
|
||||||
|
await _mareHub.InvokeAsync<List<BannedUserDto>>(Api.InvokeAdminGetBannedUsers,
|
||||||
|
token);
|
||||||
|
_mareHub.On<BannedUserDto>(Api.OnAdminUpdateOrAddBannedUser,
|
||||||
|
UpdateOrAddBannedUserCallback);
|
||||||
|
_mareHub.On<BannedUserDto>(Api.OnAdminDeleteBannedUser, DeleteBannedUserCallback);
|
||||||
|
_mareHub.On<ForbiddenFileDto>(Api.OnAdminUpdateOrAddForbiddenFile,
|
||||||
|
UpdateOrAddForbiddenFileCallback);
|
||||||
|
_mareHub.On<ForbiddenFileDto>(Api.OnAdminDeleteForbiddenFile,
|
||||||
|
DeleteForbiddenFileCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
Connected?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Logger.Verbose("Disposing " + nameof(ApiController));
|
||||||
|
|
||||||
|
_dalamudUtil.LogIn -= DalamudUtilOnLogIn;
|
||||||
|
_dalamudUtil.LogOut -= DalamudUtilOnLogOut;
|
||||||
|
|
||||||
|
Task.Run(async () => await StopConnection(_connectionCancellationTokenSource.Token));
|
||||||
|
_connectionCancellationTokenSource?.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private HubConnection BuildHubConnection(string hubName)
|
||||||
|
{
|
||||||
|
return new HubConnectionBuilder()
|
||||||
|
.WithUrl(ApiUri + hubName, options =>
|
||||||
|
{
|
||||||
|
options.Headers.Add("Authorization", SecretKey);
|
||||||
|
options.Transports = HttpTransportType.WebSockets | HttpTransportType.ServerSentEvents | HttpTransportType.LongPolling;
|
||||||
|
})
|
||||||
|
.WithAutomaticReconnect(new ForeverRetryPolicy())
|
||||||
|
.ConfigureLogging(a =>
|
||||||
|
{
|
||||||
|
a.ClearProviders().AddProvider(new DalamudLoggingProvider());
|
||||||
|
a.SetMinimumLevel(LogLevel.Warning);
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task MareHubOnClosed(Exception? arg)
|
||||||
|
{
|
||||||
|
CurrentUploads.Clear();
|
||||||
|
CurrentDownloads.Clear();
|
||||||
|
_uploadCancellationTokenSource?.Cancel();
|
||||||
|
Disconnected?.Invoke();
|
||||||
|
ServerState = ServerState.Offline;
|
||||||
|
Logger.Info("Connection closed");
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task MareHubOnReconnecting(Exception? arg)
|
||||||
|
{
|
||||||
|
ServerState = ServerState.Disconnected;
|
||||||
|
Logger.Warn("Connection closed... Reconnecting");
|
||||||
|
Logger.Warn(arg?.Message ?? string.Empty);
|
||||||
|
Logger.Warn(arg?.StackTrace ?? string.Empty);
|
||||||
|
Disconnected?.Invoke();
|
||||||
|
ServerState = ServerState.Offline;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task StopConnection(CancellationToken token)
|
||||||
|
{
|
||||||
|
if (_mareHub is not null)
|
||||||
|
{
|
||||||
|
_uploadCancellationTokenSource?.Cancel();
|
||||||
|
Logger.Info("Stopping existing connection");
|
||||||
|
_mareHub.Closed -= MareHubOnClosed;
|
||||||
|
_mareHub.Reconnecting -= MareHubOnReconnecting;
|
||||||
|
_mareHub.Reconnected -= MareHubOnReconnected;
|
||||||
|
await _mareHub.StopAsync(token);
|
||||||
|
await _mareHub.DisposeAsync();
|
||||||
|
CurrentUploads.Clear();
|
||||||
|
CurrentDownloads.Clear();
|
||||||
|
_uploadCancellationTokenSource?.Cancel();
|
||||||
|
Disconnected?.Invoke();
|
||||||
|
_mareHub = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ServerState != ServerState.Disconnected)
|
||||||
|
{
|
||||||
|
while (ServerState != ServerState.Offline)
|
||||||
|
{
|
||||||
|
await Task.Delay(16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
MareSynchronos/WebAPI/ServerState.cs
Normal file
11
MareSynchronos/WebAPI/ServerState.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace MareSynchronos.WebAPI;
|
||||||
|
|
||||||
|
public enum ServerState
|
||||||
|
{
|
||||||
|
Offline,
|
||||||
|
Disconnected,
|
||||||
|
Connected,
|
||||||
|
Unauthorized,
|
||||||
|
VersionMisMatch,
|
||||||
|
RateLimited
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user