bukson / steampy

A Steam trading library for python 3
MIT License
577 stars 157 forks source link

Does anyone have problems with the API method GetTradeOffers #382

Open xidios opened 7 months ago

xidios commented 7 months ago

{"response":{"next_cursor":0}} I get empty messages when I try to request all trade offers

crab713 commented 7 months ago

me too...

BestNathan commented 7 months ago

+1

maybe this is the steam problem?

xidios commented 7 months ago

+1

maybe this is the steam problem?

Yes, this is steam problem, but mb someone know how to fix it?

nikitabiz commented 7 months ago

I saw that Steam released a new update that affected scam projects and other skin exchange sites like market csgo

nikitabiz commented 7 months ago

Maybe it doesn't work anymore.

crab713 commented 7 months ago

This solution can temporarily serve as a substitute, looking forward to other's solution.


def get_all_trade_offer_id(steam_client: SteamClient) -> List[dict]:
        steam_id = steam_client.get_steam_id()
        response  = steam_client._session.get('https://steamcommunity.com/profiles/{}/tradeoffers/'.format(steam_id))
        soup = BeautifulSoup(response.text, 'html.parser')
        trade_offer_soup_list = soup.find_all('div', class_='tradeoffer')
        result_list = []
        for trade_offer_soup in trade_offer_soup_list:
            if 'Trade Accepted' in trade_offer_soup.text or 'Trade Cancel' in trade_offer_soup.text:
                continue
            tradeoffer_item_lists = trade_offer_soup.find_all('div', class_='tradeoffer_item_list')
            trade_item_length = []
            for i, tradeoffer_item_list in enumerate(tradeoffer_item_lists, 1):
                trade_items = tradeoffer_item_list.find_all('div', class_='trade_item')
                trade_item_length.append(len(trade_items))
            trade = {
                "trade_id": trade_offer_soup['id'].split('_')[1],
                "receive_num": trade_item_length[0],
                "send_num": trade_item_length[1]
            }
            result_list.append(trade)
        return result_list
xidios commented 7 months ago

This solution can temporarily serve as a substitute, looking forward to other's solution.

def get_all_trade_offer_id(steam_client: SteamClient) -> List[dict]:
        steam_id = steam_client.get_steam_id()
        response  = steam_client._session.get('https://steamcommunity.com/profiles/{}/tradeoffers/'.format(steam_id))
        soup = BeautifulSoup(response.text, 'html.parser')
        trade_offer_soup_list = soup.find_all('div', class_='tradeoffer')
        result_list = []
        for trade_offer_soup in trade_offer_soup_list:
            if 'Trade Accepted' in trade_offer_soup.text or 'Trade Cancel' in trade_offer_soup.text:
                continue
            tradeoffer_item_lists = trade_offer_soup.find_all('div', class_='tradeoffer_item_list')
            trade_item_length = []
            for i, tradeoffer_item_list in enumerate(tradeoffer_item_lists, 1):
                trade_items = tradeoffer_item_list.find_all('div', class_='trade_item')
                trade_item_length.append(len(trade_items))
            trade = {
                "trade_id": trade_offer_soup['id'].split('_')[1],
                "receive_num": trade_item_length[0],
                "send_num": trade_item_length[1]
            }
            result_list.append(trade)
        return result_list

ty for code, do you have any idea how to parse the description of an item?

nikitabiz commented 7 months ago

I've done it completely, I can share it with anyone who needs it.

crab713 commented 7 months ago

I've done it completely, I can share it with anyone who needs it.

please,need it.

BestNathan commented 7 months ago

I've done it completely, I can share it with anyone who needs it.

using profile or api ?

nikitabiz commented 7 months ago

Here he is)

def get_all_trade_offer_id(self):
    steam_id = self.get_steam_id()
    response = self._session.get('https://steamcommunity.com/profiles/{}/tradeoffers/'.format(steam_id))
    soup = BeautifulSoup(response.text, 'html.parser')
    trade_offer_list = soup.find_all('div', class_='tradeoffer')
    if not trade_offer_list:
        return False

    result_trade_offers_list = []

    for trade_offer in trade_offer_list:
        trade_offer_status = 2
        trade_offer_id = trade_offer['id'].split('_')[1]

        if 'Trade Accepted' in trade_offer.text or 'Trade Cancel' in trade_offer.text:
            trade_offer_status = 0

        tradeoffer_item_lists = trade_offer.find_all('div', class_='tradeoffer_item_list')
        check_items_cs2 = False
        items_class = []
        trade_items_length = []

        for i, tradeoffer_item_list in enumerate(tradeoffer_item_lists, 1):
            trade_items = tradeoffer_item_list.find_all('div', class_='trade_item')
            trade_items_length.append(len(trade_items))

            for item in trade_items:
                data_economy_item = item['data-economy-item']
                values = data_economy_item.split('/')

                items_class.append(values[2])
                check_items_cs2 = True if int(values[1]) == 730 else False

        trade_app_id = 730 if check_items_cs2 else 0
        len_trade_items_to_receive = trade_items_length[0]
        len_trade_items_to_give = trade_items_length[1]

        trade_items_to_receive = {}
        if trade_app_id == 730:
            for item in items_class:
                url = f'http://api.steampowered.com/ISteamEconomy/GetAssetClassInfo/v1?key={self._api_key}&format=json&appid=730&class_count=1&classid0={item}'
                data = self._session.get(url).json()

                icon_url = data['result'][str(item)]['icon_url']
                market_hash_name = data['result'][str(item)]['market_hash_name']

                trade_items_to_receive[f"{item}"] = {
                    "icon_url": icon_url,
                    "market_hash_name": market_hash_name
                }

        trade = {
            "tradeofferid": trade_offer_id,
            "trade_offer_state": trade_offer_status,
            "items_to_receive": trade_items_to_receive,
            "appid": trade_app_id,
            "items_to_give": len_trade_items_to_give
        }
        result_trade_offers_list.append(trade)

    return result_trade_offers_list
nikitabiz commented 7 months ago

Redo my code for yourself, because I only need partner items, and only skins from CS2

nikitabiz commented 7 months ago

in the trade dictionary, you can see what my code can get from the trade

NecroBoy commented 7 months ago

Here he is)

def get_all_trade_offer_id(self):
    steam_id = self.get_steam_id()
    response = self._session.get('https://steamcommunity.com/profiles/{}/tradeoffers/'.format(steam_id))
    soup = BeautifulSoup(response.text, 'html.parser')
    trade_offer_list = soup.find_all('div', class_='tradeoffer')
    if not trade_offer_list:
        return False

    result_trade_offers_list = []

    for trade_offer in trade_offer_list:
        trade_offer_status = 2
        trade_offer_id = trade_offer['id'].split('_')[1]

        if 'Trade Accepted' in trade_offer.text or 'Trade Cancel' in trade_offer.text:
            trade_offer_status = 0

        tradeoffer_item_lists = trade_offer.find_all('div', class_='tradeoffer_item_list')
        check_items_cs2 = False
        items_class = []
        trade_items_length = []

        for i, tradeoffer_item_list in enumerate(tradeoffer_item_lists, 1):
            trade_items = tradeoffer_item_list.find_all('div', class_='trade_item')
            trade_items_length.append(len(trade_items))

            for item in trade_items:
                data_economy_item = item['data-economy-item']
                values = data_economy_item.split('/')

                items_class.append(values[2])
                check_items_cs2 = True if int(values[1]) == 730 else False

        trade_app_id = 730 if check_items_cs2 else 0
        len_trade_items_to_receive = trade_items_length[0]
        len_trade_items_to_give = trade_items_length[1]

        trade_items_to_receive = {}
        if trade_app_id == 730:
            for item in items_class:
                url = f'http://api.steampowered.com/ISteamEconomy/GetAssetClassInfo/v1?key={self._api_key}&format=json&appid=730&class_count=1&classid0={item}'
                data = self._session.get(url).json()

                icon_url = data['result'][str(item)]['icon_url']
                market_hash_name = data['result'][str(item)]['market_hash_name']

                trade_items_to_receive[f"{item}"] = {
                    "icon_url": icon_url,
                    "market_hash_name": market_hash_name
                }

        trade = {
            "tradeofferid": trade_offer_id,
            "trade_offer_state": trade_offer_status,
            "items_to_receive": trade_items_to_receive,
            "appid": trade_app_id,
            "items_to_give": len_trade_items_to_give
        }
        result_trade_offers_list.append(trade)

    return result_trade_offers_list

market_hash_name = data['result'][str(item)]['market_hash_name'] KeyError: 'market_hash_name'

data['result'] {'5676339596': {}, 'error': 'Unable to get appearance for app 730 classID 5676339596 instanceID 0\n', 'success': False}

nikitabiz commented 7 months ago

well, then there is no skin with such a class in the game with id 730, is everything written in error?)

Marvin0729 commented 7 months ago

use web access token can get tradeoffer info at this time:

    def get_trade_offers(self, merge: bool = True,sent:int=1,received:int=1,use_webtoken=False) -> dict:
        params = {'key'if not use_webtoken else 'access_token': self._api_key if not use_webtoken else self._access_token,
                  'get_sent_offers': sent,
                  'get_received_offers': received,
                  'get_descriptions': 1,
                  'language': 'english',
                  'active_only': 1,
                  'historical_only': 0,
                  'time_historical_cutoff': ''}

        try:
            response = self.api_call('GET', 'IEconService', 'GetTradeOffers', 'v1', params)

            response = response.json()

        except json.decoder.JSONDecodeError:
            time.sleep(2)
            return self.get_trade_offers(merge,sent,received)
        response = self._filter_non_active_offers(response)

        if merge:
            response = merge_items_with_descriptions_from_offers(response)
        return response

for webapi token self._access_token, add a new function or simply added following block under the login function:

from urllib.parse import unquote

steam_login_secure_cookies = [cookie for cookie in self._session.cookies if cookie.name == 'steamLoginSecure']
cookie_value = steam_login_secure_cookies[0].value
decoded_cookie_value = unquote(cookie_value)
access_token_parts = decoded_cookie_value.split('||')
if len(access_token_parts) < 2:
    print(decoded_cookie_value)
    raise ValueError('Access token not found in steamLoginSecure cookie')

access_token = access_token_parts[1]
self._access_token = access_token

more details for web access token, see https://github.com/DoctorMcKay/node-steam-tradeoffer-manager/wiki/Access-Tokens

BestNathan commented 7 months ago

use web access token can get tradeoffer info at this time:

    def get_trade_offers(self, merge: bool = True,sent:int=1,received:int=1,use_webtoken=False) -> dict:
        params = {'key'if not use_webtoken else 'access_token': self._api_key if not use_webtoken else self._access_token,
                  'get_sent_offers': sent,
                  'get_received_offers': received,
                  'get_descriptions': 1,
                  'language': 'english',
                  'active_only': 1,
                  'historical_only': 0,
                  'time_historical_cutoff': ''}

        try:
            response = self.api_call('GET', 'IEconService', 'GetTradeOffers', 'v1', params)

            response = response.json()

        except json.decoder.JSONDecodeError:
            time.sleep(2)
            return self.get_trade_offers(merge,sent,received)
        response = self._filter_non_active_offers(response)

        if merge:
            response = merge_items_with_descriptions_from_offers(response)
        return response

for webapi token self._access_token, add a new function or simply added following block under the login function:

from urllib.parse import unquote

steam_login_secure_cookies = [cookie for cookie in self._session.cookies if cookie.name == 'steamLoginSecure']
cookie_value = steam_login_secure_cookies[0].value
decoded_cookie_value = unquote(cookie_value)
access_token_parts = decoded_cookie_value.split('||')
if len(access_token_parts) < 2:
    print(decoded_cookie_value)
    raise ValueError('Access token not found in steamLoginSecure cookie')

access_token = access_token_parts[1]
self._access_token = access_token

more details for web access token, see https://github.com/DoctorMcKay/node-steam-tradeoffer-manager/wiki/Access-Tokens

thks bro!

NecroBoy commented 7 months ago

use web access token can get tradeoffer info at this time:

    def get_trade_offers(self, merge: bool = True,sent:int=1,received:int=1,use_webtoken=False) -> dict:
        params = {'key'if not use_webtoken else 'access_token': self._api_key if not use_webtoken else self._access_token,
                  'get_sent_offers': sent,
                  'get_received_offers': received,
                  'get_descriptions': 1,
                  'language': 'english',
                  'active_only': 1,
                  'historical_only': 0,
                  'time_historical_cutoff': ''}

        try:
            response = self.api_call('GET', 'IEconService', 'GetTradeOffers', 'v1', params)

            response = response.json()

        except json.decoder.JSONDecodeError:
            time.sleep(2)
            return self.get_trade_offers(merge,sent,received)
        response = self._filter_non_active_offers(response)

        if merge:
            response = merge_items_with_descriptions_from_offers(response)
        return response

for webapi token self._access_token, add a new function or simply added following block under the login function:

from urllib.parse import unquote

steam_login_secure_cookies = [cookie for cookie in self._session.cookies if cookie.name == 'steamLoginSecure']
cookie_value = steam_login_secure_cookies[0].value
decoded_cookie_value = unquote(cookie_value)
access_token_parts = decoded_cookie_value.split('||')
if len(access_token_parts) < 2:
    print(decoded_cookie_value)
    raise ValueError('Access token not found in steamLoginSecure cookie')

access_token = access_token_parts[1]
self._access_token = access_token

more details for web access token, see https://github.com/DoctorMcKay/node-steam-tradeoffer-manager/wiki/Access-Tokens

working good, thank you very much!

CFD2 commented 7 months ago

could you create a pull request instead of having these snippets of code copy-pasted around? I don't think pasting the code in comments is the solution considering that people are starting to refer to comments instead of referring to tangible commits

bukson commented 6 months ago

Indeed, please create pr so I can fix the issue