private async Task ProcessContracts(bool isCorp, ContractNotifyGroup group, long characterID, string token) { if (group == null) { return; } var maxContracts = Settings.ContractNotificationsModule.MaxTrackingCount > 0 ? Settings.ContractNotificationsModule.MaxTrackingCount : 150; List <JsonClasses.Contract> contracts; var corpID = isCorp ? (await APIHelper.ESIAPI.GetCharacterData(Reason, characterID))?.corporation_id ?? 0 : 0; if (isCorp) { var etag = _corpEtokens.GetOrNull(characterID); var result = await APIHelper.ESIAPI.GetCorpContracts(Reason, corpID, token, etag); if (result?.Data == null || result.Data.IsNotModified) { return; } _corpEtokens.AddOrUpdateEx(characterID, result.Data.ETag); contracts = result.Result?.OrderByDescending(a => a.contract_id).ToList(); } else { var etag = _etokens.GetOrNull(characterID); var result = await APIHelper.ESIAPI.GetCharacterContracts(Reason, characterID, token, etag); if (result?.Data == null || result.Data.IsNotModified) { return; } _etokens.AddOrUpdateEx(characterID, result.Data.ETag); contracts = result.Result?.OrderByDescending(a => a.contract_id).ToList(); } if (contracts == null || !contracts.Any()) { return; } var lastContractId = contracts.FirstOrDefault()?.contract_id ?? 0; if (lastContractId == 0) { return; } var lst = !isCorp ? await SQLHelper.LoadContracts(characterID, false) : await SQLHelper.LoadContracts(characterID, true); var otherList = isCorp ? await SQLHelper.LoadContracts(characterID, false) : null; if (lst == null) { lst = new List <JsonClasses.Contract>(contracts.Where(a => _activeStatuses.ContainsCaseInsensitive(a.status)).TakeSmart(maxContracts)); await SQLHelper.SaveContracts(characterID, lst, isCorp); return; } /* * if (lst == null) * { * var cs = contracts.Where(a => !_completeStatuses.Contains(a.status)).TakeSmart(maxContracts).ToList(); * //initial cache - only progressing contracts * await SQLHelper.SaveContracts(characterID, cs, isCorp); * return; * }*/ //process cache foreach (var contract in lst.ToList()) { var freshContract = contracts.FirstOrDefault(a => a.contract_id == contract.contract_id); //check if it present if (freshContract == null) { lst.Remove(contract); continue; } if (group.Filters == null) { continue; } foreach (var filter in group.Filters.Values) { if (filter.Types.Any() && !filter.Types.Contains(contract.type)) { continue; } if (filter.Availability.Any() && !filter.Availability.ContainsCaseInsensitive(contract.availability)) { continue; } //check for completion if (_completeStatuses.Contains(freshContract.status) && filter.Statuses.Contains(freshContract.status)) { if (filter.DiscordChannelId > 0 && APIHelper.DiscordAPI.GetChannel(filter.DiscordChannelId) != null) { await PrepareFinishedDiscordMessage(filter.DiscordChannelId, freshContract, group.DefaultMention, isCorp, characterID, corpID, token, filter); } else { await LogHelper.LogWarning($"Specified filter channel ID: {filter.DiscordChannelId} is not accessible!", Category); } await LogHelper.LogModule($"--> Contract {freshContract.contract_id} is {freshContract.status}!", Category); if (lst.Contains(contract)) { lst.Remove(contract); } continue; } //check for accepted if (contract.type == "courier" && contract.status == "outstanding" && freshContract.status == "in_progress" && filter.Statuses.Contains("in_progress")) { await PrepareAcceptedDiscordMessage(filter.DiscordChannelId, freshContract, group.DefaultMention, isCorp, characterID, corpID, token, filter); var index = lst.IndexOf(contract); lst.Remove(contract); lst.Insert(index < 0 ? 0 : index, freshContract); await LogHelper.LogModule($"--> Contract {freshContract.contract_id} is accepted!", Category); continue; } } } //silently remove filtered out expired contracts var lefties = lst.Where(a => _completeStatuses.Contains(a.status)).ToList(); foreach (var lefty in lefties) { lst.Remove(lefty); } //update cache list and look for new contracts var lastRememberedId = lst.FirstOrDefault()?.contract_id ?? 0; if (lastContractId > lastRememberedId) { //get and report new contracts, forget already finished var list = contracts.Where(a => a.contract_id > lastRememberedId && !_completeStatuses.Contains(a.status)).ToList(); if (otherList != null) { list = list.Where(a => otherList.All(b => b.contract_id != a.contract_id)).ToList(); } //fix loop foreach (var contract in list) { var isCharAssignee = await APIHelper.ESIAPI.GetCharacterData(Reason, contract.assignee_id) != null; bool isCorpAssignee = false; bool isAllyAssignee = false; if (!isCharAssignee) { isCorpAssignee = await APIHelper.ESIAPI.GetCorporationData(Reason, contract.assignee_id) != null; isAllyAssignee = !isCorpAssignee; } contract.availability = isCharAssignee ? "personal" : (isCorpAssignee ? "corporation" : "alliance"); } bool stop = false; foreach (var contract in list) { foreach (var(filterName, filter) in group.Filters) { if (stop) { break; } if (!filter.Statuses.Contains(contract.status)) { continue; } //types if (filter.Types.Any() && !filter.Types.Contains(contract.type)) { continue; } //availability if (filter.Availability.Any() && !filter.Availability.ContainsCaseInsensitive(contract.availability)) { continue; } //filter by issue target if (!filter.FeedIssuedBy) { if (isCorp) { if (contract.for_corporation && contract.issuer_corporation_id == corpID) { continue; } } else { if (contract.issuer_id == characterID) { continue; } } } if (!filter.FeedIssuedTo) { if (isCorp) { if (contract.assignee_id == corpID) { continue; } else if (contract.assignee_id == characterID) { continue; } } } try { await LogHelper.LogModule($"--> New Contract {contract.contract_id} found!", Category); if (filter.DiscordChannelId != 0) { await PrepareDiscordMessage(filter.DiscordChannelId, contract, group.DefaultMention, isCorp, characterID, corpID, token, filter); } if (group.StopOnFirstFilterMatch) { stop = true; } } catch (Exception ex) { await LogHelper.LogEx($"Contract {contract.contract_id}", ex, Category); } } } if (list.Count > 0) { lst.InsertRange(0, list); //cut if (lst.Count >= maxContracts) { var count = lst.Count - maxContracts; lst.RemoveRange(lst.Count - count, count); } } } //kill dupes var rr = lst.GroupBy(a => a.contract_id).Where(a => a.Count() > 1).Select(a => a.Key).Distinct(); foreach (var item in rr) { var o = lst.FirstOrDefault(a => a.contract_id == item); if (o != null) { lst.Remove(o); } } await SQLHelper.SaveContracts(characterID, lst, isCorp); }
private async Task ProcessContracts(bool isCorp, ContractNotifyGroup group, long characterID, string token) { var maxContracts = Settings.ContractNotificationsModule.MaxTrackingCount > 0 ? Settings.ContractNotificationsModule.MaxTrackingCount : 150; List <JsonClasses.Contract> contracts; var corpID = isCorp ? (await APIHelper.ESIAPI.GetCharacterData(Reason, characterID))?.corporation_id ?? 0 : 0; if (isCorp) { var etag = _corpEtokens.GetOrNull(characterID); var result = await APIHelper.ESIAPI.GetCorpContracts(Reason, corpID, token, etag); _corpEtokens.AddOrUpdateEx(characterID, result.Data.ETag); if (result.Data.IsNotModified) { return; } contracts = result.Result?.OrderByDescending(a => a.contract_id).ToList(); } else { var etag = _etokens.GetOrNull(characterID); var result = await APIHelper.ESIAPI.GetCharacterContracts(Reason, characterID, token, etag); _etokens.AddOrUpdateEx(characterID, result.Data.ETag); if (result.Data.IsNotModified) { return; } contracts = result.Result?.OrderByDescending(a => a.contract_id).ToList(); } if (contracts == null || !contracts.Any()) { return; } var lastContractId = contracts.FirstOrDefault()?.contract_id ?? 0; if (lastContractId == 0) { return; } var lst = !isCorp ? await SQLHelper.LoadContracts(characterID, false) : await SQLHelper.LoadContracts(characterID, true); var otherList = isCorp ? await SQLHelper.LoadContracts(characterID, false) : null; if (lst == null) { var cs = contracts.Where(a => !_completeStatuses.Contains(a.status)).TakeSmart(maxContracts).ToList(); //initial cache - only progressing contracts await SQLHelper.SaveContracts(characterID, cs, isCorp); return; } //process cache foreach (var contract in lst.ToList()) { var freshContract = contracts.FirstOrDefault(a => a.contract_id == contract.contract_id); //check if it present if (freshContract == null) { lst.Remove(contract); continue; } foreach (var filter in group.Filters.Values) { if (filter.Types.Any() && !filter.Types.Contains(contract.type)) { continue; } //check for completion if (_completeStatuses.Contains(freshContract.status) && filter.Statuses.Contains(freshContract.status)) { await PrepareFinishedDiscordMessage(filter.DiscordChannelId, freshContract, group.DefaultMention, isCorp, characterID, corpID, token, filter.ShowIngameOpen); await LogHelper.LogModule($"--> Contract {freshContract.contract_id} is expired!", Category); lst.Remove(contract); continue; } //check for accepted if (contract.type == "courier" && contract.status == "outstanding" && freshContract.status == "in_progress" && filter.Statuses.Contains("in_progress")) { await PrepareAcceptedDiscordMessage(filter.DiscordChannelId, freshContract, group.DefaultMention, isCorp, characterID, corpID, token, filter.ShowIngameOpen); var index = lst.IndexOf(contract); lst.Remove(contract); lst.Insert(index, freshContract); await LogHelper.LogModule($"--> Contract {freshContract.contract_id} is accepted!", Category); continue; } } //silently remove filtered out expired contracts var lefties = lst.Where(a => _completeStatuses.Contains(a.status)).ToList(); foreach (var lefty in lefties) { lst.Remove(lefty); } } //update cache list and look for new contracts var lastRememberedId = lst.FirstOrDefault()?.contract_id ?? 0; if (lastContractId > lastRememberedId) { //get and report new contracts, forget already finished var list = contracts.Where(a => a.contract_id > lastRememberedId && !_completeStatuses.Contains(a.status)).ToList(); if (otherList != null) { list = list.Where(a => otherList.All(b => b.contract_id != a.contract_id)).ToList(); } var crFilter = group.Filters.Values.FirstOrDefault(a => a.Statuses.Contains("outstanding")); var crFilterChannel = crFilter?.DiscordChannelId ?? 0; //filter by issue target if (!crFilter?.FeedIssuedBy ?? false) { list = list.Where(a => a.issuer_id != characterID && (a.issuer_corporation_id != corpID || a.issuer_corporation_id == 0)).ToList(); } if (!crFilter?.FeedIssuedTo ?? false) { list = list.Where(a => a.assignee_id != characterID && a.assignee_id != corpID).ToList(); } if (crFilter != null && crFilter.Types.Any()) { list = list.Where(a => crFilter.Types.Contains(a.type)).ToList(); } foreach (var contract in list) { try { await LogHelper.LogModule($"--> New Contract {contract.contract_id} found!", Category); if (crFilterChannel != 0) { await PrepareDiscordMessage(crFilterChannel, contract, group.DefaultMention, isCorp, characterID, corpID, token, crFilter.ShowIngameOpen); } } catch (Exception ex) { await LogHelper.LogEx($"Contract {contract.contract_id}", ex, Category); } } if (list.Count > 0) { lst.InsertRange(0, list); //cut if (lst.Count >= maxContracts) { var count = lst.Count - maxContracts; lst.RemoveRange(lst.Count - count, count); } } } await SQLHelper.SaveContracts(characterID, lst, isCorp); }