using LightlessSync.API.Data; using LightlessSync.API.Dto.CharaData; using LightlessSync.API.Dto.User; using LightlessSync.Services.Mediator; using LightlessSync.WebAPI; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Primitives; namespace LightlessSync.Services { public class LocationShareService : DisposableMediatorSubscriberBase { private readonly DalamudUtilService _dalamudUtilService; private readonly ApiController _apiController; private IMemoryCache _locations = new MemoryCache(new MemoryCacheOptions()); private IMemoryCache _sharingStatus = new MemoryCache(new MemoryCacheOptions()); private CancellationTokenSource _resetToken = new CancellationTokenSource(); public LocationShareService(ILogger logger, LightlessMediator mediator, DalamudUtilService dalamudUtilService, ApiController apiController) : base(logger, mediator) { _dalamudUtilService = dalamudUtilService; _apiController = apiController; Mediator.Subscribe(this, (msg) => { _resetToken.Cancel(); _resetToken.Dispose(); _resetToken = new CancellationTokenSource(); }); Mediator.Subscribe(this, (msg) => { _ = _apiController.UpdateLocation(new LocationDto(new UserData(_apiController.UID, apiController.DisplayName), _dalamudUtilService.GetMapData())); _ = RequestAllLocation(); } ); Mediator.Subscribe(this, UpdateLocationList); Mediator.Subscribe(this, msg => _ = _apiController.UpdateLocation(new LocationDto(new UserData(_apiController.UID, _apiController.DisplayName), _dalamudUtilService.GetMapData()))); } private void UpdateLocationList(LocationSharingMessage msg) { if (_locations.TryGetValue(msg.User.UID, out _) && msg.LocationInfo.ServerId is 0) { _locations.Remove(msg.User.UID); return; } if ( msg.LocationInfo.ServerId is not 0 && msg.ExpireAt > DateTime.UtcNow) { AddLocationInfo(msg.User.UID, msg.LocationInfo, msg.ExpireAt); } } private void AddLocationInfo(string uid, LocationInfo location, DateTimeOffset expireAt) { var options = new MemoryCacheEntryOptions() .SetAbsoluteExpiration(expireAt) .AddExpirationToken(new CancellationChangeToken(_resetToken.Token)); _locations.Set(uid, location, options); } private async Task RequestAllLocation() { try { var (data, status) = await _apiController.RequestAllLocationInfo().ConfigureAwait(false); foreach (var dto in data) { AddLocationInfo(dto.LocationDto.User.UID, dto.LocationDto.Location, dto.ExpireAt); } foreach (var dto in status) { AddStatus(dto.User.UID, dto.ExpireAt); } } catch (Exception e) { Logger.LogError(e,"RequestAllLocation error : "); throw; } } private void AddStatus(string uid, DateTimeOffset expireAt) { var options = new MemoryCacheEntryOptions() .SetAbsoluteExpiration(expireAt) .AddExpirationToken(new CancellationChangeToken(_resetToken.Token)); _sharingStatus.Set(uid, expireAt, options); } public string GetUserLocation(string uid) { try { if (_locations.TryGetValue(uid, out var location)) { return _dalamudUtilService.LocationToString(location); } return String.Empty; } catch (Exception e) { Logger.LogError(e,"GetUserLocation error : "); throw; } } public DateTimeOffset GetSharingStatus(string uid) { try { if (_sharingStatus.TryGetValue(uid, out var expireAt)) { return expireAt; } return DateTimeOffset.MinValue; } catch (Exception e) { Logger.LogError(e,"GetSharingStatus error : "); throw; } } public void UpdateSharingStatus(List users, DateTimeOffset expireAt) { foreach (var user in users) { AddStatus(user, expireAt); } } } }