Browse Source

update SteamID

* better SteamID validation
* handling for chat SteamIDs
* improve .as_steam3 representation
* more tests

Fix #117
0.9
Rossen Georgiev 7 years ago
parent
commit
defcea5dfe
  1. 12
      steam/enums/common.py
  2. 98
      steam/steamid.py
  3. 59
      tests/test_steamid.py

12
steam/enums/common.py

@ -136,6 +136,18 @@ class EType(SteamIntEnum):
Max = 11
class EInstanceFlag(SteamIntEnum):
MMSLobby = 0x20000
Lobby = 0x40000
Clan = 0x80000
class EVanityUrlType(SteamIntEnum):
Individual = 1
Group = 2
GameGroup = 3
class EServerType(SteamIntEnum):
Invalid = -1
First = 0

98
steam/steamid.py

@ -3,7 +3,7 @@ import sys
import re
import requests
from steam.enums.base import SteamIntEnum
from steam.enums import EType, EUniverse
from steam.enums import EType, EUniverse, EInstanceFlag
from steam.util.web import make_requests_session
if sys.version_info < (3,):
@ -21,14 +21,14 @@ class ETypeChar(SteamIntEnum):
C = EType.ContentServer
g = EType.Clan
T = EType.Chat
c = EType.Chat
L = EType.Chat
L = EType.Chat # lobby chat, 'c' for clan chat
c = EType.Chat # clan chat
a = EType.AnonUser
def __str__(self):
return self.name
ETypeChars = ''.join(map(str, list(ETypeChar)))
ETypeChars = ''.join(ETypeChar.__members__.keys())
class SteamID(intBase):
@ -46,8 +46,9 @@ class SteamID(intBase):
SteamID('STEAM_1:0:2') # steam2
SteamID('[g:1:4]') # steam3
"""
EType = EType #: reference to EType
EUniverse = EUniverse #: reference to EUniverse
EType = EType #: reference to EType
EUniverse = EUniverse #: reference to EUniverse
EInstanceFlag = EInstanceFlag #: reference to EInstanceFlag
def __new__(cls, *args, **kwargs):
steam64 = make_steam64(*args, **kwargs)
@ -146,19 +147,28 @@ class SteamID(intBase):
:return: steam3 format (e.g ``[U:1:1234]``)
:rtype: :class:`str`
"""
if self.type is EType.AnonGameServer:
return "[%s:%s:%s:%s]" % (
str(ETypeChar(self.type)),
int(self.universe),
self.id,
self.instance
)
else:
return "[%s:%s:%s]" % (
str(ETypeChar(self.type)),
int(self.universe),
self.id,
)
typechar = str(ETypeChar(self.type))
instance = None
if self.type in (EType.AnonGameServer, EType.Multiseat):
instance = self.instance
elif self.type == EType.Individual:
if self.instance != 1:
instance = self.instance
elif self.type == EType.Chat:
if self.instance & EInstanceFlag.Clan:
typechar = 'c'
elif self.instance & EInstanceFlag.Lobby:
typechar = 'L'
else:
typechar = 'T'
parts = [typechar, int(self.universe), self.id]
if instance is not None:
parts.append(instance)
return '[%s]' % (':'.join(map(str, parts)))
@property
def community_url(self):
@ -178,12 +188,26 @@ class SteamID(intBase):
def is_valid(self):
"""
Check whether this SteamID is valid
:rtype: :py:class:`bool`
"""
return (self.id > 0
and self.type is not EType.Invalid
and self.universe is not EUniverse.Invalid
)
if self.id == 0:
return False
if self.type == EType.Invalid or self.type >= EType.Max:
return False
if self.universe == EUniverse.Invalid or self.universe >= EUniverse.Max:
return False
if self.type == EType.Individual and self.instance > 4:
return False
if self.type == EType.Clan and self.instance != 0:
return False
return True
def make_steam64(id=0, *args, **kwargs):
@ -306,9 +330,9 @@ def steam3_to_tuple(value):
:rtype: :class:`tuple` or :class:`None`
"""
match = re.match(r"^\["
r"(?P<type>[%s]):" # type char
r"(?P<universe>\d+):" # universe
r"(?P<id>\d+)" # accountid
r"(?P<type>[i%s]):" # type char
r"(?P<universe>[0-4]):" # universe
r"(?P<id>\d{1,10})" # accountid
r"(:(?P<instance>\d+))?" # instance
r"\]$" % ETypeChars,
value
@ -318,16 +342,24 @@ def steam3_to_tuple(value):
steam32 = int(match.group('id'))
universe = EUniverse(int(match.group('universe')))
etype = ETypeChar[match.group('type')]
typechar = match.group('type').replace('i', 'I')
etype = EType(ETypeChar[typechar])
instance = match.group('instance')
if instance is None:
if etype in (EType.Individual, EType.GameServer):
instance = 1
else:
instance = 0
else:
if typechar in 'gT':
instance = 0
elif instance is not None:
instance = int(instance)
elif typechar == 'L':
instance = EInstanceFlag.Lobby
elif typechar == 'c':
instance = EInstanceFlag.Clan
elif etype in (EType.Individual, EType.GameServer):
instance = 1
else:
instance = 0
instance = int(instance)
return (steam32, etype, universe, instance)

59
tests/test_steamid.py

@ -5,7 +5,7 @@ import vcr
import requests
from steam import steamid
from steam.steamid import SteamID, ETypeChar
from steam.enums import EType, EUniverse
from steam.enums import EType, EUniverse, EInstanceFlag
class SteamID_initialization(unittest.TestCase):
@ -181,6 +181,36 @@ class SteamID_properties(unittest.TestCase):
# just to cover in coverage
repr(SteamID())
def test_is_valid(self):
# default
self.assertFalse(SteamID().is_valid())
# id = 0
self.assertFalse(SteamID(0).is_valid())
self.assertFalse(SteamID(id=0).is_valid())
self.assertFalse(SteamID(-50).is_valid())
self.assertFalse(SteamID(id=-50).is_valid())
# id > 0
self.assertTrue(SteamID(5).is_valid())
# type out of bound
self.assertFalse(SteamID(1, EType.Max).is_valid())
# universe out of bound
self.assertFalse(SteamID(1, universe=EUniverse.Max).is_valid())
# individual
self.assertTrue(SteamID(123, EType.Individual, EUniverse.Public, instance=0).is_valid())
self.assertTrue(SteamID(123, EType.Individual, EUniverse.Public, instance=1).is_valid())
self.assertTrue(SteamID(123, EType.Individual, EUniverse.Public, instance=2).is_valid())
self.assertTrue(SteamID(123, EType.Individual, EUniverse.Public, instance=3).is_valid())
self.assertTrue(SteamID(123, EType.Individual, EUniverse.Public, instance=4).is_valid())
self.assertFalse(SteamID(123, EType.Individual, EUniverse.Public, instance=5).is_valid())
self.assertFalse(SteamID(123, EType.Individual, EUniverse.Public, instance=333).is_valid())
# clan
self.assertTrue(SteamID(1, EType.Clan, EUniverse.Public, instance=0).is_valid())
self.assertFalse(SteamID(1, EType.Clan, EUniverse.Public, instance=1).is_valid())
self.assertFalse(SteamID(1, EType.Clan, EUniverse.Public, instance=1234).is_valid())
s = SteamID(123, type=EType.Clan, universe=EUniverse.Public, instance=333)
self.assertFalse(s.is_valid())
def test_rich_comperison(self):
for test_value in [SteamID(5), 5]:
self.assertFalse(SteamID(10) == test_value)
@ -213,9 +243,13 @@ class SteamID_properties(unittest.TestCase):
def test_as_steam3(self):
self.assertEqual(SteamID('[U:1:1234]').as_steam3, '[U:1:1234]')
self.assertEqual(SteamID('[U:1:1234:56]').as_steam3, '[U:1:1234:56]')
self.assertEqual(SteamID('[g:1:4]').as_steam3, '[g:1:4]')
self.assertEqual(SteamID('[A:1:1234:567]').as_steam3, '[A:1:1234:567]')
self.assertEqual(SteamID('[G:1:1234:567]').as_steam3, '[G:1:1234]')
self.assertEqual(SteamID('[T:1:1234]').as_steam3, '[T:1:1234]')
self.assertEqual(SteamID('[c:1:1234]').as_steam3, '[c:1:1234]')
self.assertEqual(SteamID('[L:1:1234]').as_steam3, '[L:1:1234]')
def test_as_32(self):
self.assertEqual(SteamID(76580280500085312).as_32, 123456)
@ -312,6 +346,20 @@ class steamid_functions(unittest.TestCase):
def test_arg_steam3(self):
self.assertIsNone(steamid.steam3_to_tuple('invalid_format'))
self.assertIsNone(steamid.steam3_to_tuple(''))
self.assertIsNone(steamid.steam3_to_tuple(' '))
self.assertIsNone(steamid.steam3_to_tuple('[U:5:1234]'))
self.assertIsNone(steamid.steam3_to_tuple('[i:5:1234]'))
self.assertEqual(steamid.steam3_to_tuple("[i:1:1234]"),
(1234, EType.Invalid, EUniverse.Public, 0)
)
self.assertEqual(steamid.steam3_to_tuple("[I:1:1234]"),
(1234, EType.Invalid, EUniverse.Public, 0)
)
self.assertEqual(steamid.steam3_to_tuple("[U:0:1234]"),
(1234, EType.Individual, EUniverse.Invalid, 1)
)
self.assertEqual(steamid.steam3_to_tuple("[U:1:1234]"),
(1234, EType.Individual, EUniverse.Public, 1)
@ -328,4 +376,13 @@ class steamid_functions(unittest.TestCase):
self.assertEqual(steamid.steam3_to_tuple("[A:1:1234:567]"),
(1234, EType.AnonGameServer, EUniverse.Public, 567)
)
self.assertEqual(steamid.steam3_to_tuple("[T:1:1234]"),
(1234, EType.Chat, EUniverse.Public, 0)
)
self.assertEqual(steamid.steam3_to_tuple("[L:1:1234]"),
(1234, EType.Chat, EUniverse.Public, EInstanceFlag.Lobby)
)
self.assertEqual(steamid.steam3_to_tuple("[c:1:1234]"),
(1234, EType.Chat, EUniverse.Public, EInstanceFlag.Clan)
)

Loading…
Cancel
Save