Beispiel #1
0
        private async Task <ParseTradeResult> ShouldAcceptTrade(Steam.TradeOffer tradeOffer)
        {
            if (tradeOffer == null)
            {
                Logging.LogNullError(nameof(tradeOffer), Bot.BotName);
                return(ParseTradeResult.Error);
            }

            // Always accept trades when we're not losing anything
            if (tradeOffer.ItemsToGive.Count == 0)
            {
                // Unless it's steam fuckup and we're dealing with broken trade
                return(tradeOffer.ItemsToReceive.Count > 0 ? ParseTradeResult.AcceptedWithoutItemLose : ParseTradeResult.RejectedTemporarily);
            }

            // Always accept trades from SteamMasterID
            if ((tradeOffer.OtherSteamID64 != 0) && (tradeOffer.OtherSteamID64 == Bot.BotConfig.SteamMasterID))
            {
                return(ParseTradeResult.AcceptedWithItemLose);
            }

            // If we don't have SteamTradeMatcher enabled, this is the end for us
            if (!Bot.BotConfig.SteamTradeMatcher)
            {
                return(ParseTradeResult.RejectedPermanently);
            }

            // Decline trade if we're giving more count-wise
            if (tradeOffer.ItemsToGive.Count > tradeOffer.ItemsToReceive.Count)
            {
                return(ParseTradeResult.RejectedPermanently);
            }

            // Decline trade if we're losing anything but steam cards, or if it's non-dupes trade
            if (!tradeOffer.IsSteamCardsOnlyTradeForUs() || !tradeOffer.IsPotentiallyDupesTradeForUs())
            {
                return(ParseTradeResult.RejectedPermanently);
            }

            // At this point we're sure that STM trade is valid

            // Fetch trade hold duration
            byte?holdDuration = await Bot.ArchiWebHandler.GetTradeHoldDuration(tradeOffer.TradeOfferID).ConfigureAwait(false);

            if (!holdDuration.HasValue)
            {
                // If we can't get trade hold duration, reject trade temporarily
                return(ParseTradeResult.RejectedTemporarily);
            }

            // If user has a trade hold, we add extra logic
            if (holdDuration.Value > 0)
            {
                // If trade hold duration exceeds our max, or user asks for cards with short lifespan, reject the trade
                if ((holdDuration.Value > Program.GlobalConfig.MaxTradeHoldDuration) || tradeOffer.ItemsToGive.Any(item => GlobalConfig.GlobalBlacklist.Contains(item.RealAppID)))
                {
                    return(ParseTradeResult.RejectedPermanently);
                }
            }

            // Now check if it's worth for us to do the trade
            await LimitInventoryRequestsAsync().ConfigureAwait(false);

            HashSet <Steam.Item> inventory = await Bot.ArchiWebHandler.GetMyInventory(false).ConfigureAwait(false);

            if ((inventory == null) || (inventory.Count == 0))
            {
                return(ParseTradeResult.AcceptedWithItemLose);                // OK, assume that this trade is valid, we can't check our EQ
            }

            // Get appIDs we're interested in
            HashSet <uint> appIDs = new HashSet <uint>(tradeOffer.ItemsToGive.Select(item => item.RealAppID));

            // Now remove from our inventory all items we're NOT interested in
            inventory.RemoveWhere(item => !appIDs.Contains(item.RealAppID));
            inventory.TrimExcess();

            // If for some reason Valve is talking crap and we can't find mentioned items, assume OK
            if (inventory.Count == 0)
            {
                return(ParseTradeResult.AcceptedWithItemLose);
            }

            // Now let's create a map which maps items to their amount in our EQ
            Dictionary <ulong, uint> amountMap = new Dictionary <ulong, uint>();

            foreach (Steam.Item item in inventory)
            {
                uint amount;
                if (amountMap.TryGetValue(item.ClassID, out amount))
                {
                    amountMap[item.ClassID] = amount + item.Amount;
                }
                else
                {
                    amountMap[item.ClassID] = item.Amount;
                }
            }

            // Calculate our value of items to give
            List <uint> amountsToGive = new List <uint>(tradeOffer.ItemsToGive.Count);
            Dictionary <ulong, uint> amountMapToGive = new Dictionary <ulong, uint>(amountMap);

            foreach (ulong key in tradeOffer.ItemsToGive.Select(item => item.ClassID))
            {
                uint amount;
                if (!amountMapToGive.TryGetValue(key, out amount))
                {
                    amountsToGive.Add(0);
                    continue;
                }

                amountsToGive.Add(amount);
                amountMapToGive[key] = amount - 1;                 // We're giving one, so we have one less
            }

            // Sort it ascending
            amountsToGive.Sort();

            // Calculate our value of items to receive
            List <uint> amountsToReceive = new List <uint>(tradeOffer.ItemsToReceive.Count);
            Dictionary <ulong, uint> amountMapToReceive = new Dictionary <ulong, uint>(amountMap);

            foreach (ulong key in tradeOffer.ItemsToReceive.Select(item => item.ClassID))
            {
                uint amount;
                if (!amountMapToReceive.TryGetValue(key, out amount))
                {
                    amountsToReceive.Add(0);
                    continue;
                }

                amountsToReceive.Add(amount);
                amountMapToReceive[key] = amount + 1;                 // We're getting one, so we have one more
            }

            // Sort it ascending
            amountsToReceive.Sort();

            // Check actual difference
            // We sum only values at proper indexes of giving, because user might be overpaying
            int difference = amountsToGive.Select((t, i) => (int)(t - amountsToReceive[i])).Sum();

            // Trade is worth for us if the difference is greater than 0
            return(difference > 0 ? ParseTradeResult.AcceptedWithItemLose : ParseTradeResult.RejectedTemporarily);
        }
Beispiel #2
0
        private async Task <bool> ShouldAcceptTrade(Steam.TradeOffer tradeOffer)
        {
            if (tradeOffer == null)
            {
                Logging.LogNullError(nameof(tradeOffer), Bot.BotName);
                return(false);
            }

            // Always accept trades when we're not losing anything
            if (tradeOffer.ItemsToGive.Count == 0)
            {
                // Unless it's steam fuckup and we're dealing with broken trade
                return(tradeOffer.ItemsToReceive.Count > 0);
            }

            // Always accept trades from SteamMasterID
            if ((tradeOffer.OtherSteamID64 != 0) && (tradeOffer.OtherSteamID64 == Bot.BotConfig.SteamMasterID))
            {
                return(true);
            }

            // If we don't have SteamTradeMatcher enabled, this is the end for us
            if (!Bot.BotConfig.SteamTradeMatcher)
            {
                return(false);
            }

            // Decline trade if we're giving more count-wise
            if (tradeOffer.ItemsToGive.Count > tradeOffer.ItemsToReceive.Count)
            {
                return(false);
            }

            // Decline trade if we're losing anything but steam cards, or if it's non-dupes trade
            if (!tradeOffer.IsSteamCardsOnlyTradeForUs() || !tradeOffer.IsPotentiallyDupesTradeForUs())
            {
                return(false);
            }

            // At this point we're sure that STM trade is valid
            // Now check if it's worth for us to do the trade
            HashSet <Steam.Item> inventory = await Bot.ArchiWebHandler.GetMyInventory(false).ConfigureAwait(false);

            if ((inventory == null) || (inventory.Count == 0))
            {
                return(true);                // OK, assume that this trade is valid, we can't check our EQ
            }

            // Get appIDs we're interested in
            HashSet <uint> appIDs = new HashSet <uint>(tradeOffer.ItemsToGive.Select(item => item.RealAppID));

            // Now remove from our inventory all items we're NOT interested in
            inventory.RemoveWhere(item => !appIDs.Contains(item.RealAppID));
            inventory.TrimExcess();

            // If for some reason Valve is talking crap and we can't find mentioned items, assume OK
            if (inventory.Count == 0)
            {
                return(true);
            }

            // Now let's create a map which maps items to their amount in our EQ
            Dictionary <ulong, uint> amountMap = new Dictionary <ulong, uint>();

            foreach (Steam.Item item in inventory)
            {
                uint amount;
                if (amountMap.TryGetValue(item.ClassID, out amount))
                {
                    amountMap[item.ClassID] = amount + item.Amount;
                }
                else
                {
                    amountMap[item.ClassID] = item.Amount;
                }
            }

            // Calculate our value of items to give
            List <uint> amountsToGive = new List <uint>(tradeOffer.ItemsToGive.Count);

            foreach (ulong key in tradeOffer.ItemsToGive.Select(item => item.ClassID))
            {
                uint amount;
                if (!amountMap.TryGetValue(key, out amount))
                {
                    amountsToGive.Add(0);
                    continue;
                }

                amountsToGive.Add(amount);
            }

            // Sort it ascending
            amountsToGive.Sort();

            // Calculate our value of items to receive
            List <uint> amountsToReceive = new List <uint>(tradeOffer.ItemsToReceive.Count);

            foreach (ulong key in tradeOffer.ItemsToReceive.Select(item => item.ClassID))
            {
                uint amount;
                if (!amountMap.TryGetValue(key, out amount))
                {
                    amountsToReceive.Add(0);
                    continue;
                }

                amountsToReceive.Add(amount);
            }

            // Sort it ascending
            amountsToReceive.Sort();

            // Check actual difference
            int difference = amountsToGive.Select((t, i) => (int)(t - amountsToReceive[i])).Sum();

            // Trade is worth for us if the difference is greater than 0
            return(difference > 0);
        }