"""Classes to (de)serialize various struct messages""" import struct import six from six.moves import range from steam.enums import EResult, EUniverse from steam.enums.emsg import EMsg from steam.util.binary import StructReader _emsg_map = {} def get_struct(emsg): return _emsg_map.get(emsg, None) class StructMessageMeta(type): """Automatically adds subclasses of :class:`StructMessage` to the ``EMsg`` map""" def __new__(metacls, name, bases, classdict): cls = type.__new__(metacls, name, bases, classdict) if name != 'StructMessage': try: _emsg_map[EMsg[name]] = cls except KeyError: pass return cls @six.add_metaclass(StructMessageMeta) class StructMessage: def __init__(self, data=None): if data: self.load(data) def serialize(self): raise NotImplementedError def load(self, data): raise NotImplementedError class ChannelEncryptRequest(StructMessage): protocolVersion = 1 universe = EUniverse.Invalid challenge = b'' def serialize(self): return struct.pack(" 8: self.challenge = data[8:] def __str__(self): return '\n'.join(["protocolVersion: %s" % self.protocolVersion, "universe: %s" % repr(self.universe), "challenge: %s" % repr(self.challenge), ]) class ChannelEncryptResponse(StructMessage): protocolVersion = 1 keySize = 128 key = '' crc = 0 def serialize(self): return struct.pack(" m.end: m.start, m.end = m.end, m.start def __str__(self): text = ["numBans: %d" % self.numBans] for m in self.ranges: # emulate Protobuf text format text.append("ranges " + str(m).replace("\n", "\n ", 2)) return '\n'.join(text) class ClientChatMsg(StructMessage): steamIdChatter = 0 steamIdChatRoom = 0 ChatMsgType = 0 text = "" def serialize(self): rbytes = struct.pack("