diff --git a/protobuf/user_storage.proto b/protobuf/user_storage.proto index 73de647b..10c18ae3 100644 --- a/protobuf/user_storage.proto +++ b/protobuf/user_storage.proto @@ -1,11 +1,13 @@ syntax = "proto2"; message UserStorage { - optional Attributes attributes = 2; + repeated Attributes attributes = 2; } message Attributes { optional GameSettings game_settings = 22; + optional GarageItemLastSelected garage_last_selected = 23; + optional SpecialEventSeen special_event_seen = 25; } message GameSettings { @@ -16,3 +18,13 @@ message GameSettings { optional int32 power_meter_slot2 = 6; optional int32 power_meter_slot3 = 7; } + +message GarageItemLastSelected { + optional string signature = 1; + optional uint64 time = 2; +} + +message SpecialEventSeen { + optional string signature = 1; + optional uint64 time = 2; +} diff --git a/protobuf/user_storage_pb2.py b/protobuf/user_storage_pb2.py index 5316d71e..5caed2c9 100644 --- a/protobuf/user_storage_pb2.py +++ b/protobuf/user_storage_pb2.py @@ -13,7 +13,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12user_storage.proto\".\n\x0bUserStorage\x12\x1f\n\nattributes\x18\x02 \x01(\x0b\x32\x0b.Attributes\"2\n\nAttributes\x12$\n\rgame_settings\x18\x16 \x01(\x0b\x32\r.GameSettings\"\x9c\x01\n\x0cGameSettings\x12\n\n\x02\x66\x32\x18\x02 \x01(\x02\x12\x14\n\x0cleaderboards\x18\x03 \x01(\x05\x12\x19\n\x11power_meter_slot0\x18\x04 \x01(\x05\x12\x19\n\x11power_meter_slot1\x18\x05 \x01(\x05\x12\x19\n\x11power_meter_slot2\x18\x06 \x01(\x05\x12\x19\n\x11power_meter_slot3\x18\x07 \x01(\x05') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12user_storage.proto\".\n\x0bUserStorage\x12\x1f\n\nattributes\x18\x02 \x03(\x0b\x32\x0b.Attributes\"\x98\x01\n\nAttributes\x12$\n\rgame_settings\x18\x16 \x01(\x0b\x32\r.GameSettings\x12\x35\n\x14garage_last_selected\x18\x17 \x01(\x0b\x32\x17.GarageItemLastSelected\x12-\n\x12special_event_seen\x18\x19 \x01(\x0b\x32\x11.SpecialEventSeen\"\x9c\x01\n\x0cGameSettings\x12\n\n\x02\x66\x32\x18\x02 \x01(\x02\x12\x14\n\x0cleaderboards\x18\x03 \x01(\x05\x12\x19\n\x11power_meter_slot0\x18\x04 \x01(\x05\x12\x19\n\x11power_meter_slot1\x18\x05 \x01(\x05\x12\x19\n\x11power_meter_slot2\x18\x06 \x01(\x05\x12\x19\n\x11power_meter_slot3\x18\x07 \x01(\x05\"9\n\x16GarageItemLastSelected\x12\x11\n\tsignature\x18\x01 \x01(\t\x12\x0c\n\x04time\x18\x02 \x01(\x04\"3\n\x10SpecialEventSeen\x12\x11\n\tsignature\x18\x01 \x01(\t\x12\x0c\n\x04time\x18\x02 \x01(\x04') _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'user_storage_pb2', globals()) @@ -22,8 +22,12 @@ DESCRIPTOR._options = None _USERSTORAGE._serialized_start=22 _USERSTORAGE._serialized_end=68 - _ATTRIBUTES._serialized_start=70 - _ATTRIBUTES._serialized_end=120 - _GAMESETTINGS._serialized_start=123 - _GAMESETTINGS._serialized_end=279 + _ATTRIBUTES._serialized_start=71 + _ATTRIBUTES._serialized_end=223 + _GAMESETTINGS._serialized_start=226 + _GAMESETTINGS._serialized_end=382 + _GARAGEITEMLASTSELECTED._serialized_start=384 + _GARAGEITEMLASTSELECTED._serialized_end=441 + _SPECIALEVENTSEEN._serialized_start=443 + _SPECIALEVENTSEEN._serialized_end=494 # @@protoc_insertion_point(module_scope) diff --git a/zwift_offline.py b/zwift_offline.py index 81b9e927..5f77ec2f 100644 --- a/zwift_offline.py +++ b/zwift_offline.py @@ -3697,16 +3697,22 @@ def api_player_profile_user_game_storage_attributes(): if request.method == 'POST': new = user_storage_pb2.UserStorage() new.ParseFromString(request.stream.read()) - user_storage.MergeFrom(new) + for n in new.attributes: + for f in n.DESCRIPTOR.fields_by_name: + if n.HasField(f): + for a in list(user_storage.attributes): + if a.HasField(f) and (not 'signature' in getattr(a, f).DESCRIPTOR.fields_by_name \ + or getattr(a, f).signature == getattr(n, f).signature): + user_storage.attributes.remove(a) + user_storage.attributes.add().CopyFrom(n) with open(user_storage_file, 'wb') as f: f.write(user_storage.SerializeToString()) return '', 202 ret = user_storage_pb2.UserStorage() - n = int(request.args.get('n')) - if n in user_storage.attributes.DESCRIPTOR.fields_by_number: - field = user_storage.attributes.DESCRIPTOR.fields_by_number[n].name - if user_storage.attributes.HasField(field): - getattr(ret.attributes, field).CopyFrom(getattr(user_storage.attributes, field)) + for n in request.args.getlist('n'): + for a in user_storage.attributes: + if int(n) in a.DESCRIPTOR.fields_by_number and a.HasField(a.DESCRIPTOR.fields_by_number[int(n)].name): + ret.attributes.add().CopyFrom(a) return ret.SerializeToString(), 200