diff --git a/hive/utils/account.py b/hive/utils/account.py index caf38307..231e7d9e 100644 --- a/hive/utils/account.py +++ b/hive/utils/account.py @@ -11,7 +11,14 @@ def safe_profile_metadata(account): # read from posting_json_metadata, if version==2 prof = json.loads(account['posting_json_metadata'])['profile'] assert isinstance(prof, dict) - assert 'version' in prof and prof['version'] == 2 + # The "version" field is serialized inconsistently across Steem clients: + # the official condenser writes a JSON number (2), but some third-party + # clients write a JSON string ("2"). Accept both forms so that accounts + # created/updated by third-party clients are not silently dropped to + # empty profile data. + # TODO: when a new profile version is introduced, standardize on a single + # canonical type (JSON number) and migrate legacy string-form accounts. + assert 'version' in prof and prof['version'] in (2, '2') except Exception: try: # fallback to json_metadata diff --git a/tests/utils/test_utils_account.py b/tests/utils/test_utils_account.py index deb0db11..4633503f 100644 --- a/tests/utils/test_utils_account.py +++ b/tests/utils/test_utils_account.py @@ -19,6 +19,27 @@ def test_valid_account(): for key, safe_value in safe_profile.items(): assert raw_profile[key] == safe_value +def test_string_version_account(): + # Some third-party Steem clients serialize "version" as a JSON string ("2") + # instead of a number (2). Such accounts should still be parsed correctly. + raw_profile = dict( + name='Test User', + about='Hello world', + location='Earth', + website='https://example.com/', + cover_image='https://example.com/cover.jpg', + profile_image='https://example.com/avatar.jpg', + version='2', + ) + account = {'name': 'foo', 'json_metadata': '{}', + 'posting_json_metadata': json.dumps(dict(profile=raw_profile))} + + safe_profile = safe_profile_metadata(account) + assert safe_profile['name'] == 'Test User' + assert safe_profile['about'] == 'Hello world' + assert safe_profile['profile_image'] == 'https://example.com/avatar.jpg' + assert safe_profile['cover_image'] == 'https://example.com/cover.jpg' + def test_invalid_account(): raw_profile = dict( name='NameIsTooBigByOneChar',