/// <summary> /// We want to have 2 tasks running /// /// First Task will be going trough, starts to check for tradeoffers and afterwards releases the semaphore /// Second Task will set the boolean "parsingScheduled" to true, and will wait for the first Task to complete /// When the first Task completes and realeases the semaphore, /// the second Task is going to lock the semaphore and start the function to check for tradeoffers /// The next Task has to wait for the Task which is currently checking the offer /// /// Every further Task will be returned, so we have 2 Tasks working on this /// One is working on the trades /// The other is waiting for the first to complete and handling the trades afterwards /// /// We can't lock an object in async await, this is a way to lock a function to prevent it from be called multiple times before reaching the end /// </summary> /// <param name="_steamFriendsHelper"></param> /// <param name="_steamID"></param> /// <returns></returns> public async Task CheckTradeOffers(SteamFriendsHelper _steamFriendsHelper, SteamID _steamID) { lock (m_tradesSemaphore) { if (m_parsingScheduled) { return; } m_parsingScheduled = true; } await m_tradesSemaphore.WaitAsync().ConfigureAwait(false); try { lock (m_tradesSemaphore) { m_parsingScheduled = false; } await CheckForTradeOffers(_steamFriendsHelper, _steamID).ConfigureAwait(false); } finally { m_tradesSemaphore.Release(); } }
/// <summary> /// Check if the tradeoffer is sent from an admin, if so, accept it and throw a marked message, else move on /// </summary> /// <param name="_steamFriendsHelper"></param> /// <param name="_tradeOffer"></param> /// <param name="_tradePartnerID"></param> /// <returns></returns> private async Task <bool> AdminTradeOffer(SteamFriendsHelper _steamFriendsHelper, TradeOffer _tradeOffer, SteamID _tradePartnerID) { if (_steamFriendsHelper.IsBotAdmin(_tradePartnerID, m_botInfo.Admins)) { if (await m_tradeOfferWebAPI.AcceptTradeOffer(_tradeOffer.TradeOfferID).ConfigureAwait(false)) { m_logger.Warning($"Tradeoffer {_tradeOffer.TradeOfferID} was sent by admin {_tradePartnerID.ConvertToUInt64()}"); } return(true); } return(false); }
/// <summary> /// First get the summary of our tradeoffers, so we know how much tradeoffers we do have to handle /// Initialize a counter, which will be increased after every handled tradeoffer /// Receive all active tradeoffers /// /// Check if the result is not null so we do not run into an error /// Go trough every tradeoffer and check if it is active and we did not reach the amount of offers to handle /// If it is active get the tradepartners ID so we can print a message with his ID in the accept or decline function /// If we have to give Items and do not receive any items decline the trade /// Check if the tradeoffer is a donation /// If it is not a donation go on and check if the tradeoffer is sent by an admin /// If it is sent by an admin accept it and continue with the next trade /// If it is not a donation, not sent by an admin and it seems like a fair trade, check for escrow and finally check the tradeitems itself if it is a fair trade /// </summary> /// <param name="_steamFriendsHelper"></param> /// <param name="_steamID"></param> public async Task CheckForTradeOffers(SteamFriendsHelper _steamFriendsHelper, SteamID _steamID) { TradeOffersSummaryResponse tradeOfferCountToHandle = await m_tradeOfferWebAPI.GetTradeOffersSummary().ConfigureAwait(false); int tradeOfferHandledCounter = 0; GetOffersResponse receivedOffers = await m_tradeOfferWebAPI.GetReceivedActiveTradeOffers(true).ConfigureAwait(false); if (receivedOffers.TradeOffersReceived != null) { foreach (TradeOffer tradeOffer in receivedOffers.TradeOffersReceived) { if (tradeOfferHandledCounter >= tradeOfferCountToHandle.PendingReceivedCount) { break; } if (tradeOffer.TradeOfferState != ETradeOfferState.ETradeOfferStateActive) { continue; } if (tradeOffer.ConfirmationMethod == ETradeOfferConfirmationMethod.ETradeOfferConfirmationMethod_Email) { m_logger.Info($"Accept the trade offer {tradeOffer.TradeOfferID} via your email"); tradeOfferHandledCounter++; continue; } // If we were not logged on to the web or the authentication failed, go to the next tradeoffer and check it again if (!await m_steamWeb.RefreshSessionIfNeeded().ConfigureAwait(false)) { continue; } if (tradeOffer.ConfirmationMethod == ETradeOfferConfirmationMethod.ETradeOfferConfirmationMethod_MobileApp) { await m_mobileHelper.ConfirmAllTrades(m_steamWeb.SteamLogin, m_steamWeb.SteamLoginSecure, m_steamWeb.SessionID).ConfigureAwait(false); tradeOfferHandledCounter++; continue; } SteamID tradePartnerID = _steamFriendsHelper.GetSteamID(tradeOffer.AccountIDOther); // Check for a donation if (m_botInfo.AcceptDonations && await TradeOfferIsDonation(tradeOffer, tradePartnerID).ConfigureAwait(false)) { tradeOfferHandledCounter++; continue; } // Check for a tradeoffer from an admin if (await AdminTradeOffer(_steamFriendsHelper, tradeOffer, tradePartnerID).ConfigureAwait(false)) { await m_mobileHelper.ConfirmAllTrades(m_steamWeb.SteamLogin, m_steamWeb.SteamLoginSecure, m_steamWeb.SessionID).ConfigureAwait(false); tradeOfferHandledCounter++; continue; } // Check if we have to give items but do not receive any items if (tradeOffer.ItemsToGive != null && tradeOffer.ItemsToReceive == null) { await m_tradeOfferWebAPI.DeclineTradeofferShortMessage(tradeOffer.TradeOfferID).ConfigureAwait(false); tradeOfferHandledCounter++; continue; } // If we do not want to accept escrow tradeoffers, check them here before going on if (!m_botInfo.AcceptEscrow) { if (await CheckTradeOfferForEscrow(tradeOffer, tradePartnerID).ConfigureAwait(false)) { tradeOfferHandledCounter++; continue; } } await CheckTradeOffer(receivedOffers, tradeOffer, tradePartnerID).ConfigureAwait(false); tradeOfferHandledCounter++; } } }