All checks were successful
Tag and Release Lightless / tag-and-release (push) Successful in 2m27s
2.0.0 Changes: - Reworked shell finder UI with compact or list view with profile tags showing with the listing, allowing moderators to broadcast the syncshell as well to have it be used more. - Reworked user list in syncshell admin screen to have filter visible and moved away from table to its own thing, allowing to copy uid/note/alias when clicking on the name. - Reworked download bars and download box to make it look more modern, removed the jitter around, so it shouldn't vibrate around much. - Chat has been added to the top menu, working in Zone or in Syncshells to be used there. - Paired system has been revamped to make pausing and unpausing faster, and loading people should be faster as well. - Moved to the internal object table to have faster load times for users; people should load in faster - Compactor is running on a multi-threaded level instead of single-threaded; this should increase the speed of compacting files - Nameplate Service has been reworked so it wouldn't use the nameplate handler anymore. - Files can be resized when downloading to reduce load on users if they aren't compressed. (can be toggled to resize all). - Penumbra Collections are now only made when people are visible, reducing the load on boot-up when having many syncshells in your list. - Lightfinder plates have been moved away from using Nameplates, but will use an overlay. - Main UI has been changed a bit with a gradient, and on hover will glow up now. - Reworked Profile UI for Syncshell and Users to be more user-facing with more customizable items. - Reworked Settings UI to look more modern. - Performance should be better due to new systems that would dispose of the collections and better caching of items. Co-authored-by: defnotken <itsdefnotken@gmail.com> Co-authored-by: azyges <aaaaaa@aaa.aaa> Co-authored-by: choco <choco@patat.nl> Co-authored-by: cake <admin@cakeandbanana.nl> Co-authored-by: Minmoose <KennethBohr@outlook.com> Reviewed-on: #92
684 lines
24 KiB
C#
684 lines
24 KiB
C#
using Dalamud.Utility;
|
|
using LightlessSync.API.Routes;
|
|
using LightlessSync.LightlessConfiguration;
|
|
using LightlessSync.LightlessConfiguration.Models;
|
|
using LightlessSync.Services.Mediator;
|
|
using LightlessSync.WebAPI;
|
|
using Microsoft.AspNetCore.Http.Connections;
|
|
using Microsoft.Extensions.Logging;
|
|
using System.Diagnostics;
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Net.Http.Json;
|
|
using System.Security.Cryptography;
|
|
using System.Text.Json;
|
|
|
|
namespace LightlessSync.Services.ServerConfiguration;
|
|
|
|
public class ServerConfigurationManager
|
|
{
|
|
private readonly ServerConfigService _configService;
|
|
private readonly DalamudUtilService _dalamudUtil;
|
|
private readonly LightlessConfigService _lightlessConfigService;
|
|
private readonly HttpClient _httpClient;
|
|
private readonly ILogger<ServerConfigurationManager> _logger;
|
|
private readonly LightlessMediator _lightlessMediator;
|
|
private readonly NotesConfigService _notesConfig;
|
|
private readonly PairTagConfigService _pairTagConfig;
|
|
private readonly SyncshellTagConfigService _syncshellTagConfig;
|
|
private readonly int _maxCharactersFolder = 20;
|
|
|
|
public ServerConfigurationManager(ILogger<ServerConfigurationManager> logger, ServerConfigService configService,
|
|
PairTagConfigService pairTagConfig, SyncshellTagConfigService syncshellTagConfig, NotesConfigService notesConfig, DalamudUtilService dalamudUtil,
|
|
LightlessConfigService lightlessConfigService, HttpClient httpClient, LightlessMediator lightlessMediator)
|
|
{
|
|
_logger = logger;
|
|
_configService = configService;
|
|
_pairTagConfig = pairTagConfig;
|
|
_syncshellTagConfig = syncshellTagConfig;
|
|
_notesConfig = notesConfig;
|
|
_dalamudUtil = dalamudUtil;
|
|
_lightlessConfigService = lightlessConfigService;
|
|
_httpClient = httpClient;
|
|
_lightlessMediator = lightlessMediator;
|
|
EnsureMainExists();
|
|
}
|
|
|
|
public string CurrentApiUrl => CurrentServer.ServerUri;
|
|
public ServerStorage CurrentServer => _configService.Current.ServerStorage[CurrentServerIndex];
|
|
public bool SendCensusData
|
|
{
|
|
get
|
|
{
|
|
return _configService.Current.SendCensusData;
|
|
}
|
|
set
|
|
{
|
|
_configService.Current.SendCensusData = value;
|
|
_configService.Save();
|
|
}
|
|
}
|
|
|
|
public bool ShownCensusPopup
|
|
{
|
|
get
|
|
{
|
|
return _configService.Current.ShownCensusPopup;
|
|
}
|
|
set
|
|
{
|
|
_configService.Current.ShownCensusPopup = value;
|
|
_configService.Save();
|
|
}
|
|
}
|
|
|
|
public int CurrentServerIndex
|
|
{
|
|
set
|
|
{
|
|
_configService.Current.CurrentServer = value;
|
|
_configService.Save();
|
|
}
|
|
get
|
|
{
|
|
if (_configService.Current.CurrentServer < 0)
|
|
{
|
|
_configService.Current.CurrentServer = 0;
|
|
_configService.Save();
|
|
}
|
|
|
|
return _configService.Current.CurrentServer;
|
|
}
|
|
}
|
|
|
|
public (string OAuthToken, string UID)? GetOAuth2(out bool hasMulti, int serverIdx = -1)
|
|
{
|
|
ServerStorage? currentServer;
|
|
currentServer = serverIdx == -1 ? CurrentServer : GetServerByIndex(serverIdx);
|
|
if (currentServer == null)
|
|
{
|
|
currentServer = new();
|
|
Save();
|
|
}
|
|
hasMulti = false;
|
|
|
|
var charaName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult();
|
|
var worldId = _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult();
|
|
var cid = _dalamudUtil.GetCIDAsync().GetAwaiter().GetResult();
|
|
|
|
var auth = currentServer.Authentications.FindAll(f => string.Equals(f.CharacterName, charaName) && f.WorldId == worldId);
|
|
if (auth.Count >= 2)
|
|
{
|
|
_logger.LogTrace("GetOAuth2 accessed, returning null because multiple ({count}) identical characters.", auth.Count);
|
|
hasMulti = true;
|
|
return null;
|
|
}
|
|
|
|
if (auth.Count == 0)
|
|
{
|
|
_logger.LogTrace("GetOAuth2 accessed, returning null because no set up characters for {chara} on {world}", charaName, worldId);
|
|
return null;
|
|
}
|
|
|
|
if (auth.Single().LastSeenCID != cid)
|
|
{
|
|
auth.Single().LastSeenCID = cid;
|
|
_logger.LogTrace("GetOAuth2 accessed, updating CID for {chara} on {world} to {cid}", charaName, worldId, cid);
|
|
Save();
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(auth.Single().UID) && !string.IsNullOrEmpty(currentServer.OAuthToken))
|
|
{
|
|
_logger.LogTrace("GetOAuth2 accessed, returning {key} ({keyValue}) for {chara} on {world}", auth.Single().UID, string.Join("", currentServer.OAuthToken.Take(10)), charaName, worldId);
|
|
return (currentServer.OAuthToken, auth.Single().UID!);
|
|
}
|
|
|
|
_logger.LogTrace("GetOAuth2 accessed, returning null because no UID found for {chara} on {world} or OAuthToken is not configured.", charaName, worldId);
|
|
|
|
return null;
|
|
}
|
|
|
|
public string? GetSecretKey(out bool hasMulti, int serverIdx = -1)
|
|
{
|
|
ServerStorage? currentServer;
|
|
currentServer = serverIdx == -1 ? CurrentServer : GetServerByIndex(serverIdx);
|
|
if (currentServer == null)
|
|
{
|
|
currentServer = new();
|
|
Save();
|
|
}
|
|
hasMulti = false;
|
|
|
|
var charaName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult();
|
|
var worldId = _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult();
|
|
var cid = _dalamudUtil.GetCIDAsync().GetAwaiter().GetResult();
|
|
if (!currentServer.Authentications.Any() && currentServer.SecretKeys.Any())
|
|
{
|
|
currentServer.Authentications.Add(new Authentication()
|
|
{
|
|
CharacterName = charaName,
|
|
WorldId = worldId,
|
|
LastSeenCID = cid,
|
|
SecretKeyIdx = currentServer.SecretKeys.Last().Key,
|
|
});
|
|
|
|
Save();
|
|
}
|
|
|
|
var auth = currentServer.Authentications.FindAll(f => string.Equals(f.CharacterName, charaName, StringComparison.Ordinal) && f.WorldId == worldId);
|
|
if (auth.Count >= 2)
|
|
{
|
|
_logger.LogTrace("GetSecretKey accessed, returning null because multiple ({count}) identical characters.", auth.Count);
|
|
hasMulti = true;
|
|
return null;
|
|
}
|
|
|
|
if (auth.Count == 0)
|
|
{
|
|
_logger.LogTrace("GetSecretKey accessed, returning null because no set up characters for {chara} on {world}", charaName, worldId);
|
|
return null;
|
|
}
|
|
|
|
if (auth.Single().LastSeenCID != cid)
|
|
{
|
|
auth.Single().LastSeenCID = cid;
|
|
_logger.LogTrace("GetSecretKey accessed, updating CID for {chara} on {world} to {cid}", charaName, worldId, cid);
|
|
Save();
|
|
}
|
|
|
|
if (currentServer.SecretKeys.TryGetValue(auth.Single().SecretKeyIdx, out var secretKey))
|
|
{
|
|
_logger.LogTrace("GetSecretKey accessed, returning {key} ({keyValue}) for {chara} on {world}", secretKey.FriendlyName, string.Join("", secretKey.Key.Take(10)), charaName, worldId);
|
|
return secretKey.Key;
|
|
}
|
|
|
|
_logger.LogTrace("GetSecretKey accessed, returning null because no fitting key found for {chara} on {world} for idx {idx}.", charaName, worldId, auth.Single().SecretKeyIdx);
|
|
|
|
return null;
|
|
}
|
|
|
|
public string[] GetServerApiUrls()
|
|
{
|
|
return _configService.Current.ServerStorage.Select(v => v.ServerUri).ToArray();
|
|
}
|
|
|
|
public ServerStorage GetServerByIndex(int idx)
|
|
{
|
|
try
|
|
{
|
|
return _configService.Current.ServerStorage[idx];
|
|
}
|
|
catch
|
|
{
|
|
_configService.Current.CurrentServer = 0;
|
|
EnsureMainExists();
|
|
return CurrentServer!;
|
|
}
|
|
}
|
|
|
|
public string GetDiscordUserFromToken(ServerStorage server)
|
|
{
|
|
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
|
|
if (string.IsNullOrEmpty(server.OAuthToken)) return string.Empty;
|
|
try
|
|
{
|
|
var token = handler.ReadJwtToken(server.OAuthToken);
|
|
return token.Claims.First(f => string.Equals(f.Type, "discord_user", StringComparison.Ordinal)).Value!;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogWarning(ex, "Could not read jwt, resetting it");
|
|
server.OAuthToken = null;
|
|
Save();
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
public string[] GetServerNames()
|
|
{
|
|
return _configService.Current.ServerStorage.Select(v => v.ServerName).ToArray();
|
|
}
|
|
|
|
public bool HasValidConfig()
|
|
{
|
|
return CurrentServer != null && CurrentServer.Authentications.Count > 0;
|
|
}
|
|
|
|
public void Save()
|
|
{
|
|
var caller = new StackTrace().GetFrame(1)?.GetMethod()?.ReflectedType?.Name ?? "Unknown";
|
|
_logger.LogDebug("{caller} Calling config save", caller);
|
|
_configService.Save();
|
|
}
|
|
|
|
public void SelectServer(int idx)
|
|
{
|
|
var previousIndex = _configService.Current.CurrentServer;
|
|
_configService.Current.CurrentServer = idx;
|
|
CurrentServer!.FullPause = false;
|
|
Save();
|
|
|
|
if (previousIndex != idx)
|
|
{
|
|
var serverUrl = CurrentServer.ServerUri;
|
|
_lightlessMediator.Publish(new ActiveServerChangedMessage(serverUrl));
|
|
}
|
|
}
|
|
|
|
internal void AddCurrentCharacterToServer(int serverSelectionIndex = -1)
|
|
{
|
|
if (serverSelectionIndex == -1) serverSelectionIndex = CurrentServerIndex;
|
|
var server = GetServerByIndex(serverSelectionIndex);
|
|
if (server.Authentications.Exists(c => string.Equals(c.CharacterName, _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult(), StringComparison.Ordinal)
|
|
&& c.WorldId == _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult()))
|
|
return;
|
|
|
|
server.Authentications.Add(new Authentication()
|
|
{
|
|
CharacterName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult(),
|
|
WorldId = _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult(),
|
|
SecretKeyIdx = !server.UseOAuth2 ? server.SecretKeys.Last().Key : -1,
|
|
LastSeenCID = _dalamudUtil.GetCIDAsync().GetAwaiter().GetResult()
|
|
});
|
|
Save();
|
|
}
|
|
|
|
internal void AddEmptyCharacterToServer(int serverSelectionIndex)
|
|
{
|
|
var server = GetServerByIndex(serverSelectionIndex);
|
|
server.Authentications.Add(new Authentication()
|
|
{
|
|
SecretKeyIdx = server.SecretKeys.Count != 0 ? server.SecretKeys.First().Key : -1,
|
|
});
|
|
Save();
|
|
}
|
|
|
|
internal void AddOpenPairTag(string tag)
|
|
{
|
|
CurrentPairTagStorage().OpenPairTags.Add(tag);
|
|
_pairTagConfig.Save();
|
|
}
|
|
|
|
internal void AddServer(ServerStorage serverStorage)
|
|
{
|
|
_configService.Current.ServerStorage.Add(serverStorage);
|
|
Save();
|
|
}
|
|
|
|
internal void AddPairTag(string tag)
|
|
{
|
|
if (tag.Length <= _maxCharactersFolder)
|
|
{
|
|
CurrentPairTagStorage().ServerAvailablePairTags.Add(tag);
|
|
_pairTagConfig.Save();
|
|
_lightlessMediator.Publish(new RefreshUiMessage());
|
|
}
|
|
else
|
|
{
|
|
_logger.LogInformation("Couldn't save/add {tag}. Name too long to be saved", tag);
|
|
}
|
|
}
|
|
|
|
internal void AddSyncshellTag(string tag)
|
|
{
|
|
if (tag.Length <= _maxCharactersFolder)
|
|
{
|
|
CurrentSyncshellTagStorage().ServerAvailableSyncshellTags.Add(tag);
|
|
_syncshellTagConfig.Save();
|
|
_lightlessMediator.Publish(new RefreshUiMessage());
|
|
}
|
|
else
|
|
{
|
|
_logger.LogInformation("Couldn't save/add {tag}. Name too long to be saved", tag);
|
|
}
|
|
}
|
|
|
|
internal void AddTagForUid(string uid, string tagName)
|
|
{
|
|
if (CurrentPairTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags))
|
|
{
|
|
tags.Add(tagName);
|
|
_lightlessMediator.Publish(new RefreshUiMessage());
|
|
}
|
|
else
|
|
{
|
|
CurrentPairTagStorage().UidServerPairedUserTags[uid] = [tagName];
|
|
}
|
|
|
|
_pairTagConfig.Save();
|
|
}
|
|
|
|
internal void AddTagForSyncshell(string syncshellName, string tagName)
|
|
{
|
|
if (CurrentSyncshellTagStorage().SyncshellPairedTags.TryGetValue(syncshellName, out var tags))
|
|
{
|
|
tags.Add(tagName);
|
|
_lightlessMediator.Publish(new RefreshUiMessage());
|
|
}
|
|
else
|
|
{
|
|
CurrentSyncshellTagStorage().SyncshellPairedTags[syncshellName] = [tagName];
|
|
}
|
|
|
|
_syncshellTagConfig.Save();
|
|
}
|
|
|
|
internal bool ContainsOpenPairTag(string tag) => CurrentPairTagStorage().OpenPairTags.Contains(tag);
|
|
|
|
internal bool ContainsPairTag(string uid, string tag)
|
|
{
|
|
if (CurrentPairTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags))
|
|
{
|
|
return tags.Contains(tag, StringComparer.Ordinal);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
internal bool ContainsSyncshellTag(string name, string tag)
|
|
{
|
|
if (CurrentSyncshellTagStorage().SyncshellPairedTags.TryGetValue(name, out var tags))
|
|
{
|
|
return tags.Contains(tag, StringComparer.Ordinal);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
internal void DeleteServer(ServerStorage selectedServer)
|
|
{
|
|
if (Array.IndexOf(_configService.Current.ServerStorage.ToArray(), selectedServer) <
|
|
_configService.Current.CurrentServer)
|
|
{
|
|
_configService.Current.CurrentServer--;
|
|
}
|
|
|
|
_configService.Current.ServerStorage.Remove(selectedServer);
|
|
Save();
|
|
}
|
|
|
|
internal string? GetNoteForGid(string gID)
|
|
{
|
|
if (CurrentNotesStorage().GidServerComments.TryGetValue(gID, out var note))
|
|
{
|
|
if (string.IsNullOrEmpty(note)) return null;
|
|
return note;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
internal string? GetNoteForUid(string uid)
|
|
{
|
|
if (CurrentNotesStorage().UidServerComments.TryGetValue(uid, out var note))
|
|
{
|
|
if (string.IsNullOrEmpty(note)) return null;
|
|
return note;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
internal HashSet<string> GetServerAvailablePairTags() => CurrentPairTagStorage().ServerAvailablePairTags;
|
|
|
|
internal HashSet<string> GetServerAvailableSyncshellTags() => CurrentSyncshellTagStorage().ServerAvailableSyncshellTags;
|
|
|
|
internal Dictionary<string, List<string>> GetUidServerPairedUserTags() => CurrentPairTagStorage().UidServerPairedUserTags;
|
|
|
|
internal HashSet<string> GetUidsForPairTag(string tag) => CurrentPairTagStorage().UidServerPairedUserTags.Where(p => p.Value.Contains(tag, StringComparer.Ordinal)).Select(p => p.Key).ToHashSet(StringComparer.Ordinal);
|
|
|
|
internal HashSet<string> GetNamesForSyncshellTag(string tag) => CurrentSyncshellTagStorage().SyncshellPairedTags.Where(p => p.Value.Contains(tag, StringComparer.Ordinal)).Select(p => p.Key).ToHashSet(StringComparer.Ordinal);
|
|
|
|
internal bool HasPairTags(string uid) => CurrentPairTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags) && tags.Count != 0;
|
|
|
|
internal bool HasSyncshellTags(string name) => CurrentSyncshellTagStorage().SyncshellPairedTags.TryGetValue(name, out var tags) && tags.Count != 0;
|
|
|
|
internal void RemoveCharacterFromServer(int serverSelectionIndex, Authentication item)
|
|
{
|
|
var server = GetServerByIndex(serverSelectionIndex);
|
|
server.Authentications.Remove(item);
|
|
Save();
|
|
}
|
|
|
|
internal void RemoveOpenPairTag(string tag)
|
|
{
|
|
CurrentPairTagStorage().OpenPairTags.Remove(tag);
|
|
_pairTagConfig.Save();
|
|
}
|
|
|
|
internal void RemovePairTag(string tag)
|
|
{
|
|
RemoveTag(CurrentPairTagStorage().ServerAvailablePairTags, tag);
|
|
_pairTagConfig.Save();
|
|
_lightlessMediator.Publish(new RefreshUiMessage());
|
|
}
|
|
|
|
internal void RemoveSyncshellTag(string tag)
|
|
{
|
|
RemoveTag(CurrentSyncshellTagStorage().ServerAvailableSyncshellTags, tag, true);
|
|
_syncshellTagConfig.Save();
|
|
_lightlessMediator.Publish(new RefreshUiMessage());
|
|
}
|
|
|
|
internal void RemoveTag(HashSet<string> storage, string tag, bool syncshell = false)
|
|
{
|
|
storage.Remove(tag);
|
|
if (syncshell)
|
|
{
|
|
foreach (var uid in GetNamesForSyncshellTag(tag))
|
|
{
|
|
RemoveTagForSyncshell(uid, tag, save: false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (var uid in GetUidsForPairTag(tag))
|
|
{
|
|
RemoveTagForUid(uid, tag, save: false);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void RemoveTagForUid(string uid, string tagName, bool save = true)
|
|
{
|
|
if (CurrentPairTagStorage().UidServerPairedUserTags.TryGetValue(uid, out var tags))
|
|
{
|
|
tags.Remove(tagName);
|
|
|
|
if (save)
|
|
{
|
|
_pairTagConfig.Save();
|
|
_lightlessMediator.Publish(new RefreshUiMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void RemoveTagForSyncshell(string name, string tagName, bool save = true)
|
|
{
|
|
if (CurrentSyncshellTagStorage().SyncshellPairedTags.TryGetValue(name, out var tags))
|
|
{
|
|
tags.Remove(tagName);
|
|
|
|
if (save)
|
|
{
|
|
_syncshellTagConfig.Save();
|
|
_lightlessMediator.Publish(new RefreshUiMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void RenamePairTag(string oldName, string newName) => RenameTag(CurrentPairTagStorage().UidServerPairedUserTags, CurrentPairTagStorage().ServerAvailablePairTags, oldName, newName);
|
|
|
|
internal void RenameSyncshellTag(string oldName, string newName) => RenameTag(CurrentSyncshellTagStorage().SyncshellPairedTags, CurrentSyncshellTagStorage().ServerAvailableSyncshellTags, oldName, newName);
|
|
|
|
internal void RenameTag(Dictionary<string, List<string>> tags, HashSet<string> storage, string oldName, string newName)
|
|
{
|
|
if (newName.Length < _maxCharactersFolder)
|
|
{
|
|
storage.Remove(oldName);
|
|
storage.Add(newName);
|
|
foreach (var existingTags in tags.Select(k => k.Value))
|
|
{
|
|
if (existingTags.Remove(oldName))
|
|
existingTags.Add(newName);
|
|
}
|
|
_lightlessMediator.Publish(new RefreshUiMessage());
|
|
}
|
|
else
|
|
{
|
|
_logger.LogInformation("Couldn't save/add {tag}. Name too long to be saved", newName);
|
|
}
|
|
}
|
|
|
|
internal void SaveNotes() => _notesConfig.Save();
|
|
|
|
internal void SetNoteForGid(string gid, string note, bool save = true)
|
|
{
|
|
if (string.IsNullOrEmpty(gid)) return;
|
|
|
|
CurrentNotesStorage().GidServerComments[gid] = note;
|
|
if (save)
|
|
_notesConfig.Save();
|
|
}
|
|
|
|
internal void SetNoteForUid(string uid, string note, bool save = true)
|
|
{
|
|
if (string.IsNullOrEmpty(uid)) return;
|
|
|
|
CurrentNotesStorage().UidServerComments[uid] = note;
|
|
if (save)
|
|
_notesConfig.Save();
|
|
}
|
|
|
|
internal void AutoPopulateNoteForUid(string uid, string note)
|
|
{
|
|
if (!_lightlessConfigService.Current.AutoPopulateEmptyNotesFromCharaName
|
|
|| GetNoteForUid(uid) != null)
|
|
return;
|
|
|
|
SetNoteForUid(uid, note, save: true);
|
|
}
|
|
|
|
private ServerNotesStorage CurrentNotesStorage()
|
|
{
|
|
TryCreateCurrentNotesStorage();
|
|
return _notesConfig.Current.ServerNotes[CurrentApiUrl];
|
|
}
|
|
|
|
private PairTagStorage CurrentPairTagStorage()
|
|
{
|
|
TryCreateCurrentPairTagStorage();
|
|
return _pairTagConfig.Current.ServerTagStorage[CurrentApiUrl];
|
|
}
|
|
|
|
private SyncshellTagStorage CurrentSyncshellTagStorage()
|
|
{
|
|
TryCreateCurrentSyncshellTagStorage();
|
|
return _syncshellTagConfig.Current.ServerTagStorage[CurrentApiUrl];
|
|
}
|
|
|
|
private void EnsureMainExists()
|
|
{
|
|
if (_configService.Current.ServerStorage.Count == 0 || !string.Equals(_configService.Current.ServerStorage[0].ServerUri, ApiController.MainServiceUri, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
_configService.Current.ServerStorage.Insert(0, new ServerStorage() { ServerUri = ApiController.MainServiceUri, ServerName = ApiController.MainServer, UseOAuth2 = true });
|
|
}
|
|
Save();
|
|
}
|
|
|
|
private void TryCreateCurrentNotesStorage()
|
|
{
|
|
if (!_notesConfig.Current.ServerNotes.ContainsKey(CurrentApiUrl))
|
|
{
|
|
_notesConfig.Current.ServerNotes[CurrentApiUrl] = new();
|
|
}
|
|
}
|
|
|
|
private void TryCreateCurrentPairTagStorage()
|
|
{
|
|
if (!_pairTagConfig.Current.ServerTagStorage.ContainsKey(CurrentApiUrl))
|
|
{
|
|
_pairTagConfig.Current.ServerTagStorage[CurrentApiUrl] = new();
|
|
}
|
|
}
|
|
|
|
private void TryCreateCurrentSyncshellTagStorage()
|
|
{
|
|
if (!_syncshellTagConfig.Current.ServerTagStorage.ContainsKey(CurrentApiUrl))
|
|
{
|
|
_syncshellTagConfig.Current.ServerTagStorage[CurrentApiUrl] = new();
|
|
}
|
|
}
|
|
|
|
public async Task<Dictionary<string, string>> GetUIDsWithDiscordToken(string serverUri, string token)
|
|
{
|
|
try
|
|
{
|
|
var baseUri = serverUri.Replace("wss://", "https://").Replace("ws://", "http://");
|
|
var oauthCheckUri = LightlessAuth.GetUIDsFullPath(new Uri(baseUri));
|
|
using var request = new HttpRequestMessage(HttpMethod.Get, oauthCheckUri);
|
|
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
|
|
using var response = await _httpClient.SendAsync(request).ConfigureAwait(false);
|
|
var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
|
return await JsonSerializer.DeserializeAsync<Dictionary<string, string>>(responseStream).ConfigureAwait(false) ?? [];
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogWarning(ex, "Failure getting UIDs");
|
|
return [];
|
|
}
|
|
}
|
|
|
|
public async Task<Uri?> CheckDiscordOAuth(string serverUri)
|
|
{
|
|
try
|
|
{
|
|
var baseUri = serverUri.Replace("wss://", "https://").Replace("ws://", "http://");
|
|
var oauthCheckUri = LightlessAuth.GetDiscordOAuthEndpointFullPath(new Uri(baseUri));
|
|
var response = await _httpClient.GetFromJsonAsync<Uri?>(oauthCheckUri).ConfigureAwait(false);
|
|
return response;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogWarning(ex, "Failure checking for Discord Auth");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public async Task<string?> GetDiscordOAuthToken(Uri discordAuthUri, string serverUri, CancellationToken token)
|
|
{
|
|
var sessionId = BitConverter.ToString(RandomNumberGenerator.GetBytes(64)).Replace("-", "").ToLower();
|
|
Util.OpenLink(discordAuthUri.ToString() + "?sessionId=" + sessionId);
|
|
|
|
string? discordToken = null;
|
|
using CancellationTokenSource timeOutCts = new();
|
|
timeOutCts.CancelAfter(TimeSpan.FromSeconds(60));
|
|
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(timeOutCts.Token, token);
|
|
try
|
|
{
|
|
var baseUri = serverUri.Replace("wss://", "https://").Replace("ws://", "http://");
|
|
var oauthCheckUri = LightlessAuth.GetDiscordOAuthTokenFullPath(new Uri(baseUri), sessionId);
|
|
var response = await _httpClient.GetAsync(oauthCheckUri, linkedCts.Token).ConfigureAwait(false);
|
|
discordToken = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogWarning(ex, "Failure getting Discord Token");
|
|
return null;
|
|
}
|
|
|
|
if (discordToken == null)
|
|
return null;
|
|
|
|
return discordToken;
|
|
}
|
|
|
|
public HttpTransportType GetTransport()
|
|
{
|
|
return CurrentServer.HttpTransportType;
|
|
}
|
|
|
|
public void SetTransportType(HttpTransportType httpTransportType)
|
|
{
|
|
CurrentServer.HttpTransportType = httpTransportType;
|
|
Save();
|
|
}
|
|
} |