diff --git a/README.md b/README.md index defb64bd..fc707f7c 100644 --- a/README.md +++ b/README.md @@ -377,6 +377,10 @@ To enable support for multiple users perform the steps below: To enable all-time leaderboards (override 60 minutes live results and 90 days personal records), create a file ``all_time_leaderboards.txt`` in the ``storage`` directory. +### Entitlements + +To unlock entitlements (special equipment), create a file ``unlock_entitlements.txt`` in the ``storage`` directory. + ## Community Discord server and Strava club Please join the community supported [Discord](https://discord.gg/GMdn8F8) server and [Strava](https://www.strava.com/clubs/zoffline) club. diff --git a/data/entitlements.txt b/data/entitlements.txt new file mode 100644 index 00000000..931e16d4 --- /dev/null +++ b/data/entitlements.txt @@ -0,0 +1,558 @@ +[ + { + "id": 1687, + "name": "ENTITLEMENT_CYCLING_HEADGEAR_ONBOARDINGHELMET" + }, + { + "id": 1688, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_BACKPEDAL2023" + }, + { + "id": 1689, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_EZR2023" + }, + { + "id": 1690, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_NOVEMBERFONDO2023" + }, + { + "id": 1691, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_DECEMBERFONDO2023" + }, + { + "id": 1692, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_TEAMCASTELLI2023" + }, + { + "id": 1693, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_ABUSSYNERGYMEN2023" + }, + { + "id": 1694, + "name": "ENTITLEMENT_PAINTJOB_ZWIFTACADEMY2023" + }, + { + "id": 1695, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_EINTRACHTFRANKFURT2023" + }, + { + "id": 1696, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_ZIRT2023" + }, + { + "id": 1697, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_BL13LADIES2023" + }, + { + "id": 1698, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_ABUSSYNERGYLADIES2023" + }, + { + "id": 1699, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_PRIMORRWBESPORTS2023" + }, + { + "id": 1700, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_TWENTY242024" + }, + { + "id": 1701, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_5W4T2023" + }, + { + "id": 1702, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_BASEPERFORMANCE2023" + }, + { + "id": 1703, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_WLBB2023" + }, + { + "id": 1704, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_CHASINGRACING2023" + }, + { + "id": 1705, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_TOYOTAELITE2023" + }, + { + "id": 1706, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_ZTBR2023" + }, + { + "id": 1707, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_PAINCAVEHEROES2023" + }, + { + "id": 1708, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_SUNRISERACING2023" + }, + { + "id": 1709, + "name": "ENTITLEMENT_RUNNING_OUTFIT_TOURDEZWIFT2024" + }, + { + "id": 1710, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_JANUARYFONDO2023" + }, + { + "id": 1711, + "name": "ENTITLEMENT_RUNNING_SHORTS_INNOVATIONRUNNING2023" + }, + { + "id": 1712, + "name": "ENTITLEMENT_RUNNING_SHORTS_FILMMYRUN2023" + }, + { + "id": 1713, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_COALITIONALPHAMEN2023" + }, + { + "id": 1714, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_COALITIONALPHAWMN2023" + }, + { + "id": 1715, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_METIER2023" + }, + { + "id": 1716, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_AMANI2023" + }, + { + "id": 1717, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_HPLCYCLING2023" + }, + { + "id": 1718, + "name": "ENTITLEMENT_RUNNING_OUTFIT_ZLDR2023" + }, + { + "id": 1719, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_RAPHA5002023" + }, + { + "id": 1720, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_DODDIEAID2024" + }, + { + "id": 1721, + "name": "ENTITLEMENT_RUNNING_SHIRT_TUGAZRUN2023" + }, + { + "id": 1722, + "name": "ENTITLEMENT_CYCLING_JERSEY_COMPANIES_LETAPE2024" + }, + { + "id": 1723, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_USAC_CHAMP2024" + }, + { + "id": 1724, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_CYCLINGCANADA_CHAMP2024" + }, + { + "id": 1725, + "name": "ENTITLEMENT_CYCLING_JERSEY_DCF_CHAMPS2024" + }, + { + "id": 1726, + "name": "ENTITLEMENT_CYCLING_JERSEY_FFC_CHAMPS2024" + }, + { + "id": 1727, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_FDJSUEZ2024" + }, + { + "id": 1728, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_MOVISTAR2024" + }, + { + "id": 1729, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_INEOS2024" + }, + { + "id": 1730, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_CANYONSRAMRACING2024" + }, + { + "id": 1731, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_PROJECTECHELON2024" + }, + { + "id": 1732, + "name": "ENTITLEMENT_SOCKS_SOCKS_ZWIFTGAMES2024" + }, + { + "id": 1733, + "name": "ENTITLEMENT_CYCLING_GLOVES_ZWIFTGAMES2024" + }, + { + "id": 1734, + "name": "ENTITLEMENT_CYCLING_HEADGEAR_CYCLINGCAPZWIFTGAMESGOLDCAP2024" + }, + { + "id": 1735, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_ZWIFTGAMESKIT2024" + }, + { + "id": 1736, + "name": "ENTITLEMENT_CYCLING_SHOES_ADIDASTEMPOBOA2024L" + }, + { + "id": 1737, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_TOUROFMARCH2024" + }, + { + "id": 1738, + "name": "ENTITLEMENT_CYCLING_HEADGEAR_BIGSPIN2024" + }, + { + "id": 1739, + "name": "ENTITLEMENT_WHEELS_ZWIFTBIGSPIN2024" + }, + { + "id": 1740, + "name": "ENTITLEMENT_CYCLING_HEADGEAR_HEADPHONESBIGSPIN2024" + }, + { + "id": 1741, + "name": "ENTITLEMENT_CYCLING_SHOES_BIGSPIN2024L" + }, + { + "id": 1742, + "name": "ENTITLEMENT_SOCKS_SOCKS_BIGSPIN" + }, + { + "id": 1743, + "name": "ENTITLEMENT_CYCLING_HEADGEAR_BUCKETHAT_BIGSPINUNIONFLAG2024" + }, + { + "id": 1744, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_SUNFLOWERKIT2024" + }, + { + "id": 1745, + "name": "ENTITLEMENT_CYCLING_JERSEY_ORIGINALS_BIGSPIN2024MAKURIKIT" + }, + { + "id": 1746, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_TOMUNDERGROUNDMAP2024" + }, + { + "id": 1747, + "name": "ENTITLEMENT_GLASSES_BIGSPINGLASSES2024" + }, + { + "id": 1748, + "name": "ENTITLEMENT_RUNNING_HEADGEAR_BACKWARDSBASEBALLCAP2024" + }, + { + "id": 1749, + "name": "ENTITLEMENT_CYCLING_JERSEY_ORIGINALS_BASEBALLKIT2024" + }, + { + "id": 1750, + "name": "ENTITLEMENT_BIKE_ZWIFTCONCEPTGOLD" + }, + { + "id": 1751, + "name": "ENTITLEMENT_RUNNING_HEADGEAR_CYCLINGCAP_BIGSPINBERET2024" + }, + { + "id": 1752, + "name": "ENTITLEMENT_BIKE_ZWIFTBIGSPINCRUISER2024" + }, + { + "id": 1753, + "name": "ENTITLEMENT_GLASSES_OAKLEYSPHAERA" + }, + { + "id": 1754, + "name": "ENTITLEMENT_CYCLING_HEADGEAR_CYCLINGCAPSPRINGTRAININGHAT2024" + }, + { + "id": 1755, + "name": "ENTITLEMENT_GLASSES_SPRINGTRAININGSUNGLASSES2024" + }, + { + "id": 1756, + "name": "ENTITLEMENT_CYCLING_JERSEY_ORIGINALS_SPRINGTRAINING2024" + }, + { + "id": 1757, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_SCFCHAMP2024" + }, + { + "id": 1758, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_AUSCYCLINGCHAMP2024" + }, + { + "id": 1759, + "name": "ENTITLEMENT_SOCKS_SOCKS_CONFETTITRAILS" + }, + { + "id": 1760, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_SLT2024BLUE" + }, + { + "id": 1761, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_SLT2024GREEN" + }, + { + "id": 1762, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_SLT2024GREY" + }, + { + "id": 1763, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_SLT2024ORANGE" + }, + { + "id": 1764, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_SLT2024PALEBLUE" + }, + { + "id": 1765, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_SLT2024PALEGREEN" + }, + { + "id": 1766, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_SLT2024PALEORANGE" + }, + { + "id": 1767, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_SLT2024PINK" + }, + { + "id": 1768, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_SLT2024PURPLE" + }, + { + "id": 1769, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_SLT2024RED" + }, + { + "id": 1770, + "name": "ENTITLEMENT_RUNNING_SHIRT_SLT2024BLUE" + }, + { + "id": 1771, + "name": "ENTITLEMENT_RUNNING_SHIRT_SLT2024GREEN" + }, + { + "id": 1772, + "name": "ENTITLEMENT_RUNNING_SHIRT_SLT2024GREY" + }, + { + "id": 1773, + "name": "ENTITLEMENT_RUNNING_SHIRT_SLT2024ORANGE" + }, + { + "id": 1774, + "name": "ENTITLEMENT_RUNNING_SHIRT_SLT2024PALEBLUE" + }, + { + "id": 1775, + "name": "ENTITLEMENT_RUNNING_SHIRT_SLT2024PALEGREEN" + }, + { + "id": 1776, + "name": "ENTITLEMENT_RUNNING_SHIRT_SLT2024PALEORANGE" + }, + { + "id": 1777, + "name": "ENTITLEMENT_RUNNING_SHIRT_SLT2024PINK" + }, + { + "id": 1778, + "name": "ENTITLEMENT_RUNNING_SHIRT_SLT2024PURPLE" + }, + { + "id": 1779, + "name": "ENTITLEMENT_RUNNING_SHIRT_SLT2024RED" + }, + { + "id": 1780, + "name": "ENTITLEMENT_RUNNING_SHORTS_SLT2024" + }, + { + "id": 1781, + "name": "ENTITLEMENT_BIKE_PINARELLODOGMAX2024" + }, + { + "id": 1782, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_RIDELIKEKING2024" + }, + { + "id": 1783, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_ALPECINDECEUNINCK2024" + }, + { + "id": 1784, + "name": "ENTITLEMENT_GLASSES_OAKLEYSUTROGLASSES" + }, + { + "id": 1785, + "name": "ENTITLEMENT_GLASSES_OAKLEYENCODERGLASSES" + }, + { + "id": 1786, + "name": "ENTITLEMENT_BIKE_PINARELLOESPADA" + }, + { + "id": 1787, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_PRIDEON2024" + }, + { + "id": 1788, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_TDF2024" + }, + { + "id": 1789, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_ROYALAIRFORCE2024" + }, + { + "id": 1790, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_LEVELVELO2024" + }, + { + "id": 1791, + "name": "ENTITLEMENT_PAINTJOB_ZWIFTRIDE2024" + }, + { + "id": 1792, + "name": "ENTITLEMENT_CYCLING_JERSEY_ORIGINALS_ZWIFTACADEMY2024" + }, + { + "id": 1793, + "name": "ENTITLEMENT_RUNNING_OUTFIT_WAHOO_RUN2024" + }, + { + "id": 1794, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_TDFFAZ2024" + }, + { + "id": 1795, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_ATTACUSCYCLESQUAD2024" + }, + { + "id": 1796, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_LGBTQZWIFTERS2024" + }, + { + "id": 1797, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_ZWIFTNL2024" + }, + { + "id": 1798, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_RELENTLESS2024" + }, + { + "id": 1799, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_FRENCHYFUZION2024" + }, + { + "id": 1800, + "name": "ENTITLEMENT_RUNNING_OUTFIT_HISP2024" + }, + { + "id": 1801, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_NVDMCOACHING2024" + }, + { + "id": 1802, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_LIVALULA2024" + }, + { + "id": 1803, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_ABSOLUTEMOTION2024" + }, + { + "id": 1804, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_FENIXDECEUNINCK2024" + }, + { + "id": 1805, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_HPH2024" + }, + { + "id": 1806, + "name": "ENTITLEMENT_CYCLING_JERSEY_COMPANIES_GCN2024" + }, + { + "id": 1807, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_BIKEALICIOUS2024" + }, + { + "id": 1808, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_INTERMARCHEWANTY2024" + }, + { + "id": 1809, + "name": "ENTITLEMENT_BIKE_CANYONAEROAD2024" + }, + { + "id": 1810, + "name": "ENTITLEMENT_PAINTJOB_CANYONAEROADALPECIN2024" + }, + { + "id": 1811, + "name": "ENTITLEMENT_PAINTJOB_CANYONAEROADZA2024" + }, + { + "id": 1812, + "name": "ENTITLEMENT_PAINTJOB_CANYONAEROADSRAM2024" + }, + { + "id": 1813, + "name": "ENTITLEMENT_CYCLING_JERSEY_CLUBS_ROCACORBACOLLECTIVE2024" + }, + { + "id": 1814, + "name": "ENTITLEMENT_CYCLING_JERSEY_PRO_TEAMS_FREDDYOVETT2024" + }, + { + "id": 1815, + "name": "ENTITLEMENT_RUNNING_HEADGEAR_RUNNINGCAPTOUROFWATOPIA2024" + }, + { + "id": 1816, + "name": "ENTITLEMENT_CYCLING_HEADGEAR_RUNNINGCAPTOUROFWATOPIA2024" + }, + { + "id": 1817, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_ZWIFTWORLDSERIESELITE2024" + }, + { + "id": 1818, + "name": "ENTITLEMENT_CYCLING_JERSEY_ZWIFTWORLDSERIESCOMMUNITY2024" + }, + { + "id": 1819, + "name": "ENTITLEMENT_RUNNING_SHOES_RUNNINGSHOES_TOUROFWATOPIA2024" + }, + { + "id": 1820, + "name": "ENTITLEMENT_CYCLING_SHOES_CYCLINGSHOES_TOUROFWATOPIA2024L" + }, + { + "id": 1821, + "name": "ENTITLEMENT_RUNNING_OUTFIT_TOUROFWATOPIA2024" + }, + { + "id": 1822, + "name": "ENTITLEMENT_CYCLING_JERSEY_EVENTS_TOUROFWATOPIA2024" + }, + { + "id": 1823, + "name": "ENTITLEMENT_SOCKS_SOCKS_TOUROFWATOPIA2024" + }, + { + "id": 1824, + "name": "ENTITLEMENT_BIKE_PINARELLODOGMAF2024" + }, + { + "id": 1825, + "name": "ENTITLEMENT_PAINTJOB_PINARELLODOGMAFZWIFT2024" + } +] \ No newline at end of file diff --git a/protobuf/profile.proto b/protobuf/profile.proto index ce4e0107..1a57c403 100644 --- a/protobuf/profile.proto +++ b/protobuf/profile.proto @@ -211,7 +211,7 @@ message ProfileEntitlement { USE = 4; } - optional int64 f2 = 2; // always -1 when "RIDE"; increasing small value when "USE" (437, 438, 911, ..., 1229) + optional int64 id = 2; // always -1 when "RIDE"; increasing small value when "USE" (437, 438, 911, ..., 1229) optional ProfileEntitlementStatus status = 3; enum ProfileEntitlementStatus { diff --git a/protobuf/profile_pb2.py b/protobuf/profile_pb2.py index 63dc74f0..cf9d2b5f 100644 --- a/protobuf/profile_pb2.py +++ b/protobuf/profile_pb2.py @@ -13,7 +13,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rprofile.proto\"\xd5\x1d\n\rPlayerProfile\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x14\n\x0cserver_realm\x18\x02 \x01(\x03\x12\r\n\x05\x65mail\x18\x03 \x01(\t\x12\x12\n\nfirst_name\x18\x04 \x01(\t\x12\x11\n\tlast_name\x18\x05 \x01(\t\x12\x0f\n\x07is_male\x18\x06 \x01(\x08\x12\n\n\x02\x66\x37\x18\x07 \x01(\t\x12\x17\n\x0fweight_in_grams\x18\t \x01(\r\x12\x0b\n\x03\x66tp\x18\n \x01(\r\x12\x0b\n\x03\x66\x31\x31\x18\x0b \x01(\r\x12\x11\n\tbody_type\x18\x0c \x01(\r\x12\x11\n\thair_type\x18\r \x01(\r\x12\x18\n\x10\x66\x61\x63ial_hair_type\x18\x0e \x01(\r\x12\x18\n\x10ride_helmet_type\x18\x0f \x01(\r\x12\x14\n\x0cglasses_type\x18\x10 \x01(\r\x12\x17\n\x0fride_shoes_type\x18\x11 \x01(\r\x12\x17\n\x0fride_socks_type\x18\x12 \x01(\r\x12\x13\n\x0bride_gloves\x18\x13 \x01(\r\x12\x13\n\x0bride_jersey\x18\x14 \x01(\x07\x12\x0b\n\x03\x66\x32\x31\x18\x15 \x01(\x07\x12\x18\n\x10\x62ike_wheel_front\x18\x16 \x01(\x07\x12\x17\n\x0f\x62ike_wheel_rear\x18\x17 \x01(\x07\x12\x12\n\nbike_frame\x18\x18 \x01(\x07\x12\x0b\n\x03\x66\x32\x35\x18\x19 \x01(\x07\x12\x0b\n\x03\x66\x32\x36\x18\x1a \x01(\x07\x12\x19\n\x11\x62ike_frame_colour\x18\x1b \x01(\x06\x12\x0b\n\x03\x66\x32\x38\x18\x1c \x01(\x06\x12\x0b\n\x03\x66\x32\x39\x18\x1d \x01(\x06\x12\x0b\n\x03\x66\x33\x30\x18\x1e \x01(\x06\x12\x0b\n\x03\x66\x33\x31\x18\x1f \x01(\x06\x12\x0b\n\x03\x66\x33\x32\x18 \x01(\x06\x12\x12\n\nsaved_game\x18! \x01(\x0c\x12\x14\n\x0c\x63ountry_code\x18\" \x01(\r\x12 \n\x18total_distance_in_meters\x18# \x01(\r\x12 \n\x18\x65levation_gain_in_meters\x18$ \x01(\r\x12\x1e\n\x16time_ridden_in_minutes\x18% \x01(\r\x12\x1b\n\x13total_in_kom_jersey\x18& \x01(\r\x12!\n\x19total_in_sprinters_jersey\x18\' \x01(\r\x12\x1e\n\x16total_in_orange_jersey\x18( \x01(\r\x12\x18\n\x10total_watt_hours\x18) \x01(\r\x12\x1d\n\x15height_in_millimeters\x18* \x01(\r\x12\x0b\n\x03\x64ob\x18+ \x01(\t\x12\x16\n\x0emax_heart_rate\x18, \x01(\r\x12\x1b\n\x13\x63onnected_to_strava\x18- \x01(\x08\x12\x10\n\x08total_xp\x18. \x01(\r\x12\x18\n\x10total_gold_drops\x18/ \x01(\r\x12 \n\x0bplayer_type\x18\x30 \x01(\x0e\x32\x0b.PlayerType\x12\x19\n\x11\x61\x63hievement_level\x18\x31 \x01(\r\x12\x12\n\nuse_metric\x18\x32 \x01(\x08\x12\x16\n\x0estrava_premium\x18\x33 \x01(\x08\x12&\n\x12power_source_model\x18\x34 \x01(\x0e\x32\n.PowerType\x12\x0b\n\x03\x66\x35\x33\x18\x35 \x01(\r\x12\x0b\n\x03\x66\x35\x34\x18\x36 \x01(\r\x12\x0b\n\x03\x61ge\x18\x37 \x01(\r\x12\x0b\n\x03\x66\x35\x36\x18\x38 \x01(\x07\x12\x0b\n\x03\x66\x35\x37\x18\x39 \x01(\r\x12\x18\n\x10large_avatar_url\x18: \x01(\t\x12\x14\n\x0cprivacy_bits\x18; \x01(\x06\x12)\n\x0c\x65ntitlements\x18< \x03(\x0b\x32\x13.ProfileEntitlement\x12\x30\n\x0csocial_facts\x18= \x01(\x0b\x32\x1a.PlayerProfile.SocialFacts\x12$\n\rfollow_status\x18> \x01(\x0e\x32\r.FollowStatus\x12#\n\x1b\x63onnected_to_training_peaks\x18? \x01(\x08\x12 \n\x18\x63onnected_to_todays_plan\x18@ \x01(\x08\x12\x38\n\x10\x65nrolled_program\x18\x41 \x01(\x0e\x32\x1e.PlayerProfile.EnrolledProgram\x12\x15\n\rtodayplan_url\x18\x42 \x01(\t\x12\x0b\n\x03\x66\x36\x37\x18\x43 \x01(\r\x12\x16\n\x0erun_shirt_type\x18\x44 \x01(\x07\x12\x17\n\x0frun_shorts_type\x18\x45 \x01(\x07\x12\x16\n\x0erun_shoes_type\x18\x46 \x01(\x07\x12\x16\n\x0erun_socks_type\x18G \x01(\x07\x12\x17\n\x0frun_helmet_type\x18H \x01(\x07\x12\x19\n\x11run_arm_accessory\x18I \x01(\x07\x12\x1a\n\x12total_run_distance\x18J \x01(\r\x12#\n\x1btotal_run_experience_points\x18K \x01(\r\x12\x0b\n\x03\x66\x37\x36\x18L \x01(\x07\x12\x0b\n\x03\x66\x37\x37\x18M \x01(\x07\x12\x0b\n\x03\x66\x37\x38\x18N \x01(\x07\x12\x0b\n\x03\x66\x37\x39\x18O \x01(\x07\x12\x0b\n\x03\x66\x38\x30\x18P \x01(\r\x12\x0b\n\x03\x66\x38\x31\x18Q \x01(\r\x12#\n\x0csubscription\x18R \x01(\x0b\x32\r.Subscription\x12\x1d\n\x15mix_panel_distinct_id\x18S \x01(\t\x12\x1d\n\x15run_achievement_level\x18T \x01(\r\x12!\n\x19total_run_time_in_minutes\x18U \x01(\r\x12\x15\n\x05sport\x18V \x01(\x0e\x32\x06.Sport\x12\x1d\n\x15utc_offset_in_minutes\x18W \x01(\r\x12!\n\x19\x63onnected_to_under_armour\x18X \x01(\x08\x12\x1a\n\x12preferred_language\x18Y \x01(\t\x12\x13\n\x0bhair_colour\x18Z \x01(\r\x12\x1a\n\x12\x66\x61\x63ial_hair_colour\x18[ \x01(\r\x12\x0b\n\x03\x66\x39\x32\x18\\ \x01(\r\x12\x0b\n\x03\x66\x39\x33\x18] \x01(\r\x12\x19\n\x11run_shorts_length\x18^ \x01(\r\x12\x0b\n\x03\x66\x39\x35\x18_ \x01(\r\x12\x18\n\x10run_socks_length\x18` \x01(\r\x12\x0b\n\x03\x66\x39\x37\x18\x61 \x01(\r\x12\x19\n\x11ride_socks_length\x18\x62 \x01(\r\x12\x0b\n\x03\x66\x39\x39\x18\x63 \x01(\r\x12\x0c\n\x04\x66\x31\x30\x30\x18\x64 \x01(\r\x12\x0c\n\x04\x66\x31\x30\x31\x18\x65 \x01(\r\x12\x0c\n\x04\x66\x31\x30\x32\x18\x66 \x01(\r\x12\x0c\n\x04\x66\x31\x30\x33\x18g \x01(\r\x12\x0c\n\x04\x66\x31\x30\x34\x18h \x01(\r\x12\x1d\n\x15\x63onnected_to_withings\x18i \x01(\x08\x12\x1b\n\x13\x63onnected_to_fitbit\x18j \x01(\x08\x12\x1c\n\x14launched_game_client\x18l \x01(\t\x12\x1b\n\x13\x63urrent_activity_id\x18m \x01(\x03\x12\x1b\n\x13\x63onnected_to_garmin\x18n \x01(\x08\x12*\n\treminders\x18o \x03(\x0b\x32\x17.PlayerProfile.Reminder\x12\x0c\n\x04\x66\x31\x31\x32\x18p \x01(\x08\x12&\n\x12private_attributes\x18q \x03(\x0b\x32\n.Attribute\x12%\n\x11public_attributes\x18r \x03(\x0b\x32\n.Attribute\x12\x1a\n\x12total_run_calories\x18s \x01(\x05\x12\x0c\n\x04\x66\x31\x31\x36\x18t \x01(\x03\x12\x1f\n\x17run_time_1mi_in_seconds\x18u \x01(\x05\x12\x1f\n\x17run_time_5km_in_seconds\x18v \x01(\x05\x12 \n\x18run_time_10km_in_seconds\x18w \x01(\x05\x12)\n!run_time_half_marathon_in_seconds\x18x \x01(\x05\x12)\n!run_time_full_marathon_in_seconds\x18y \x01(\x05\x12\x0c\n\x04\x66\x31\x32\x32\x18z \x01(\x05\x12@\n\x14\x63ycling_organization\x18{ \x01(\x0e\x32\".PlayerProfile.CyclingOrganization\x12\x0c\n\x04\x66\x31\x32\x34\x18| \x01(\t\x12\x36\n\x18\x64\x65\x66\x61ult_activity_privacy\x18} \x01(\x0e\x32\x14.ActivityPrivacyType\x12\x1e\n\x16\x63onnected_to_runtastic\x18~ \x01(\x08\x12)\n\x10property_changes\x18\x7f \x03(\x0b\x32\x0f.PropertyChange\x1a\xa7\x02\n\x0bSocialFacts\x12\x12\n\nprofile_id\x18\x01 \x01(\x03\x12\x17\n\x0f\x66ollowers_count\x18\x02 \x01(\x05\x12\x17\n\x0f\x66ollowees_count\x18\x03 \x01(\x05\x12\x31\n)followees_in_common_with_logged_in_player\x18\x04 \x01(\x05\x12:\n#follower_status_of_logged_in_player\x18\x05 \x01(\x0e\x32\r.FollowStatus\x12:\n#followee_status_of_logged_in_player\x18\x06 \x01(\x0e\x32\r.FollowStatus\x12\'\n\x1fis_favorite_of_logged_in_player\x18\x07 \x01(\x08\x1a\x9c\x01\n\x08Reminder\x12\n\n\x02\x66\x31\x18\x01 \x01(\x03\x12\n\n\x02\x66\x32\x18\x02 \x01(\t\x12\n\n\x02\x66\x33\x18\x03 \x01(\x03\x12\x34\n\x02\x66\x34\x18\x04 \x03(\x0b\x32(.PlayerProfile.Reminder.ReminderProperty\x1a\x36\n\x10ReminderProperty\x12\n\n\x02\x66\x31\x18\x01 \x01(\x03\x12\n\n\x02\x66\x32\x18\x02 \x01(\t\x12\n\n\x02\x66\x33\x18\x03 \x01(\t\"|\n\x0f\x45nrolledProgram\x12\x14\n\x10\x45NROLLEDPROGRAM0\x10\x00\x12\x11\n\rZWIFT_ACADEMY\x10\x01\x12\x14\n\x10\x45NROLLEDPROGRAM2\x10\x02\x12\x14\n\x10\x45NROLLEDPROGRAM3\x10\x03\x12\x14\n\x10\x45NROLLEDPROGRAM4\x10\x04\"w\n\x13\x43yclingOrganization\x12\x16\n\x12NO_CYCLING_LICENSE\x10\x00\x12\x18\n\x14\x43YCLING_SOUTH_AFRICA\x10\x01\x12\x15\n\x11\x43YCLING_AUSTRALIA\x10\x02\x12\x17\n\x13\x43YCLING_NEW_ZEALAND\x10\x03\"2\n\x0ePlayerProfiles\x12 \n\x08profiles\x18\x01 \x03(\x0b\x32\x0e.PlayerProfile\"\xb0\x06\n\x12ProfileEntitlement\x12\x31\n\x04type\x18\x01 \x01(\x0e\x32#.ProfileEntitlement.EntitlementType\x12\n\n\x02\x66\x32\x18\x02 \x01(\x03\x12<\n\x06status\x18\x03 \x01(\x0e\x32,.ProfileEntitlement.ProfileEntitlementStatus\x12\x0e\n\x06period\x18\x04 \x01(\t\x12\x17\n\x0f\x62\x65gin_time_unix\x18\x05 \x01(\r\x12\x15\n\rend_time_unix\x18\x06 \x01(\r\x12\x12\n\nkilometers\x18\x07 \x01(\r\x12\x1c\n\x14\x62\x65gin_total_distance\x18\x08 \x01(\r\x12\x1a\n\x12\x65nd_total_distance\x18\t \x01(\r\x12\x0e\n\x06source\x18\n \x01(\t\x12.\n\x08platform\x18\x0b \x01(\x0e\x32\x1c.ProfileEntitlement.Platform\x12\x19\n\x11renewal_date_unix\x18\x0c \x01(\r\x12\x18\n\x10new_trial_system\x18\r \x01(\x08\x12/\n\tplatforms\x18\x0e \x03(\x0e\x32\x1c.ProfileEntitlement.Platform\"L\n\x0f\x45ntitlementType\x12\x14\n\x10\x45NTITLEMENTTYPE0\x10\x00\x12\x08\n\x04RIDE\x10\x01\x12\x07\n\x03RUN\x10\x02\x12\x07\n\x03ROW\x10\x03\x12\x07\n\x03USE\x10\x04\"\x91\x01\n\x18ProfileEntitlementStatus\x12\x16\n\x12\x45NTITLEMENTSTATUS0\x10\x00\x12\x0b\n\x07\x45XPIRED\x10\x01\x12\n\n\x06\x41\x43TIVE\x10\x02\x12\x0c\n\x08\x43\x41NCELED\x10\x03\x12\x0c\n\x08INACTIVE\x10\x04\x12(\n$APPLIED_AS_SUBSCRIPTION_TRIAL_PERIOD\x10\x05\"\x86\x01\n\x08Platform\x12\x10\n\x0cPLATFORM_OSX\x10\x00\x12\x0f\n\x0bPLATFORM_PC\x10\x01\x12\x10\n\x0cPLATFORM_IOS\x10\x02\x12\x14\n\x10PLATFORM_ANDROID\x10\x03\x12\x11\n\rPLATFORM_TVOS\x10\x04\x12\r\n\tPLATFORM5\x10\x05\x12\r\n\tPLATFORM6\x10\x06\"\xcc\x02\n\x0cSubscription\x12&\n\x07gateway\x18\x01 \x01(\x0e\x32\x15.Subscription.Gateway\x12\x30\n\x06status\x18\x02 \x01(\x0e\x32 .Subscription.SubscriptionStatus\"#\n\x07Gateway\x12\r\n\tBRAINTREE\x10\x00\x12\t\n\x05\x41PPLE\x10\x01\"\xbc\x01\n\x12SubscriptionStatus\x12\x07\n\x03NEW\x10\x00\x12\x0b\n\x07\x45XPIRED\x10\x01\x12\n\n\x06\x41\x43TIVE\x10\x02\x12\x0c\n\x08\x43\x41NCELED\x10\x03\x12\x0c\n\x08PAST_DUE\x10\x04\x12\x0b\n\x07PENDING\x10\x05\x12\x0c\n\x08SUBERROR\x10\x06\x12\x10\n\x0cUNRECOGNIZED\x10\x07\x12\x0b\n\x07UNKNOWN\x10\x08\x12\x1f\n\x1b\x41\x43TIVE_WITH_PAYMENT_FAILURE\x10\t\x12\r\n\tABANDONED\x10\n\"\x96\x01\n\x0ePropertyChange\x12)\n\rproperty_name\x18\x01 \x02(\x0e\x32\x12.PropertyChange.Id\x12\x14\n\x0c\x63hange_count\x18\x02 \x01(\x05\x12\x13\n\x0bmax_changes\x18\x03 \x01(\x05\".\n\x02Id\x12\t\n\x05TYPE0\x10\x00\x12\x11\n\rDATE_OF_BIRTH\x10\x01\x12\n\n\x06GENDER\x10\x02\"X\n\tAttribute\x12\n\n\x02id\x18\x01 \x02(\x05\x12\x14\n\x0cnumber_value\x18\x02 \x01(\x03\x12\x13\n\x0b\x66loat_value\x18\x03 \x01(\x02\x12\x14\n\x0cstring_value\x18\x05 \x01(\t\"\x1e\n\x10\x41\x63hievementEntry\x12\n\n\x02id\x18\x01 \x02(\x05\"7\n\x0c\x41\x63hievements\x12\'\n\x0c\x61\x63hievements\x18\x01 \x03(\x0b\x32\x11.AchievementEntry\"6\n\x12\x42\x65stEffortPointMsg\x12\r\n\x05power\x18\x01 \x02(\x01\x12\x11\n\ttimestamp\x18\x02 \x01(\x04\"\x9b\x02\n\x18PowerCurveAggregationMsg\x12\x33\n\x05watts\x18\x01 \x03(\x0b\x32$.PowerCurveAggregationMsg.WattsEntry\x12?\n\x0cwatts_per_kg\x18\x02 \x03(\x0b\x32).PowerCurveAggregationMsg.WattsPerKgEntry\x1a\x41\n\nWattsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.BestEffortPointMsg:\x02\x38\x01\x1a\x46\n\x0fWattsPerKgEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.BestEffortPointMsg:\x02\x38\x01*;\n\x13\x41\x63tivityPrivacyType\x12\n\n\x06PUBLIC\x10\x00\x12\x0b\n\x07PRIVATE\x10\x01\x12\x0b\n\x07\x46RIENDS\x10\x02*E\n\x05Sport\x12\x0b\n\x07\x43YCLING\x10\x00\x12\x0b\n\x07RUNNING\x10\x01\x12\n\n\x06ROWING\x10\x02\x12\n\n\x06SPORT3\x10\x03\x12\n\n\x06SPORT4\x10\x04*\x9f\x01\n\nPlayerType\x12\x0f\n\x0bPLAYERTYPE0\x10\x00\x12\n\n\x06NORMAL\x10\x01\x12\x0f\n\x0bPRO_CYCLIST\x10\x02\x12\x0f\n\x0bZWIFT_STAFF\x10\x03\x12\x0e\n\nAMBASSADOR\x10\x04\x12\x0c\n\x08VERIFIED\x10\x05\x12\x07\n\x03ZED\x10\x06\x12\x07\n\x03ZAC\x10\x07\x12\x12\n\x0ePRO_TRIATHLETE\x10\x08\x12\x0e\n\nPRO_RUNNER\x10\t*B\n\tPowerType\x12\x17\n\nPT_UNKNOWN\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x12\x0e\n\nPT_VIRTUAL\x10\x00\x12\x0c\n\x08PT_METER\x10\x01*\x9e\x01\n\x0c\x46ollowStatus\x12\x11\n\rFOLLOWSTATUS0\x10\x00\x12\x0b\n\x07UNKNOWN\x10\x01\x12\x16\n\x12REQUESTS_TO_FOLLOW\x10\x02\x12\x10\n\x0cIS_FOLLOWING\x10\x03\x12\x15\n\x11HAS_BEEN_DECLINED\x10\x07\x12\x0e\n\nIS_BLOCKED\x10\x04\x12\x13\n\x0fNO_RELATIONSHIP\x10\x05\x12\x08\n\x04SELF\x10\x06') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rprofile.proto\"\xd5\x1d\n\rPlayerProfile\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x14\n\x0cserver_realm\x18\x02 \x01(\x03\x12\r\n\x05\x65mail\x18\x03 \x01(\t\x12\x12\n\nfirst_name\x18\x04 \x01(\t\x12\x11\n\tlast_name\x18\x05 \x01(\t\x12\x0f\n\x07is_male\x18\x06 \x01(\x08\x12\n\n\x02\x66\x37\x18\x07 \x01(\t\x12\x17\n\x0fweight_in_grams\x18\t \x01(\r\x12\x0b\n\x03\x66tp\x18\n \x01(\r\x12\x0b\n\x03\x66\x31\x31\x18\x0b \x01(\r\x12\x11\n\tbody_type\x18\x0c \x01(\r\x12\x11\n\thair_type\x18\r \x01(\r\x12\x18\n\x10\x66\x61\x63ial_hair_type\x18\x0e \x01(\r\x12\x18\n\x10ride_helmet_type\x18\x0f \x01(\r\x12\x14\n\x0cglasses_type\x18\x10 \x01(\r\x12\x17\n\x0fride_shoes_type\x18\x11 \x01(\r\x12\x17\n\x0fride_socks_type\x18\x12 \x01(\r\x12\x13\n\x0bride_gloves\x18\x13 \x01(\r\x12\x13\n\x0bride_jersey\x18\x14 \x01(\x07\x12\x0b\n\x03\x66\x32\x31\x18\x15 \x01(\x07\x12\x18\n\x10\x62ike_wheel_front\x18\x16 \x01(\x07\x12\x17\n\x0f\x62ike_wheel_rear\x18\x17 \x01(\x07\x12\x12\n\nbike_frame\x18\x18 \x01(\x07\x12\x0b\n\x03\x66\x32\x35\x18\x19 \x01(\x07\x12\x0b\n\x03\x66\x32\x36\x18\x1a \x01(\x07\x12\x19\n\x11\x62ike_frame_colour\x18\x1b \x01(\x06\x12\x0b\n\x03\x66\x32\x38\x18\x1c \x01(\x06\x12\x0b\n\x03\x66\x32\x39\x18\x1d \x01(\x06\x12\x0b\n\x03\x66\x33\x30\x18\x1e \x01(\x06\x12\x0b\n\x03\x66\x33\x31\x18\x1f \x01(\x06\x12\x0b\n\x03\x66\x33\x32\x18 \x01(\x06\x12\x12\n\nsaved_game\x18! \x01(\x0c\x12\x14\n\x0c\x63ountry_code\x18\" \x01(\r\x12 \n\x18total_distance_in_meters\x18# \x01(\r\x12 \n\x18\x65levation_gain_in_meters\x18$ \x01(\r\x12\x1e\n\x16time_ridden_in_minutes\x18% \x01(\r\x12\x1b\n\x13total_in_kom_jersey\x18& \x01(\r\x12!\n\x19total_in_sprinters_jersey\x18\' \x01(\r\x12\x1e\n\x16total_in_orange_jersey\x18( \x01(\r\x12\x18\n\x10total_watt_hours\x18) \x01(\r\x12\x1d\n\x15height_in_millimeters\x18* \x01(\r\x12\x0b\n\x03\x64ob\x18+ \x01(\t\x12\x16\n\x0emax_heart_rate\x18, \x01(\r\x12\x1b\n\x13\x63onnected_to_strava\x18- \x01(\x08\x12\x10\n\x08total_xp\x18. \x01(\r\x12\x18\n\x10total_gold_drops\x18/ \x01(\r\x12 \n\x0bplayer_type\x18\x30 \x01(\x0e\x32\x0b.PlayerType\x12\x19\n\x11\x61\x63hievement_level\x18\x31 \x01(\r\x12\x12\n\nuse_metric\x18\x32 \x01(\x08\x12\x16\n\x0estrava_premium\x18\x33 \x01(\x08\x12&\n\x12power_source_model\x18\x34 \x01(\x0e\x32\n.PowerType\x12\x0b\n\x03\x66\x35\x33\x18\x35 \x01(\r\x12\x0b\n\x03\x66\x35\x34\x18\x36 \x01(\r\x12\x0b\n\x03\x61ge\x18\x37 \x01(\r\x12\x0b\n\x03\x66\x35\x36\x18\x38 \x01(\x07\x12\x0b\n\x03\x66\x35\x37\x18\x39 \x01(\r\x12\x18\n\x10large_avatar_url\x18: \x01(\t\x12\x14\n\x0cprivacy_bits\x18; \x01(\x06\x12)\n\x0c\x65ntitlements\x18< \x03(\x0b\x32\x13.ProfileEntitlement\x12\x30\n\x0csocial_facts\x18= \x01(\x0b\x32\x1a.PlayerProfile.SocialFacts\x12$\n\rfollow_status\x18> \x01(\x0e\x32\r.FollowStatus\x12#\n\x1b\x63onnected_to_training_peaks\x18? \x01(\x08\x12 \n\x18\x63onnected_to_todays_plan\x18@ \x01(\x08\x12\x38\n\x10\x65nrolled_program\x18\x41 \x01(\x0e\x32\x1e.PlayerProfile.EnrolledProgram\x12\x15\n\rtodayplan_url\x18\x42 \x01(\t\x12\x0b\n\x03\x66\x36\x37\x18\x43 \x01(\r\x12\x16\n\x0erun_shirt_type\x18\x44 \x01(\x07\x12\x17\n\x0frun_shorts_type\x18\x45 \x01(\x07\x12\x16\n\x0erun_shoes_type\x18\x46 \x01(\x07\x12\x16\n\x0erun_socks_type\x18G \x01(\x07\x12\x17\n\x0frun_helmet_type\x18H \x01(\x07\x12\x19\n\x11run_arm_accessory\x18I \x01(\x07\x12\x1a\n\x12total_run_distance\x18J \x01(\r\x12#\n\x1btotal_run_experience_points\x18K \x01(\r\x12\x0b\n\x03\x66\x37\x36\x18L \x01(\x07\x12\x0b\n\x03\x66\x37\x37\x18M \x01(\x07\x12\x0b\n\x03\x66\x37\x38\x18N \x01(\x07\x12\x0b\n\x03\x66\x37\x39\x18O \x01(\x07\x12\x0b\n\x03\x66\x38\x30\x18P \x01(\r\x12\x0b\n\x03\x66\x38\x31\x18Q \x01(\r\x12#\n\x0csubscription\x18R \x01(\x0b\x32\r.Subscription\x12\x1d\n\x15mix_panel_distinct_id\x18S \x01(\t\x12\x1d\n\x15run_achievement_level\x18T \x01(\r\x12!\n\x19total_run_time_in_minutes\x18U \x01(\r\x12\x15\n\x05sport\x18V \x01(\x0e\x32\x06.Sport\x12\x1d\n\x15utc_offset_in_minutes\x18W \x01(\r\x12!\n\x19\x63onnected_to_under_armour\x18X \x01(\x08\x12\x1a\n\x12preferred_language\x18Y \x01(\t\x12\x13\n\x0bhair_colour\x18Z \x01(\r\x12\x1a\n\x12\x66\x61\x63ial_hair_colour\x18[ \x01(\r\x12\x0b\n\x03\x66\x39\x32\x18\\ \x01(\r\x12\x0b\n\x03\x66\x39\x33\x18] \x01(\r\x12\x19\n\x11run_shorts_length\x18^ \x01(\r\x12\x0b\n\x03\x66\x39\x35\x18_ \x01(\r\x12\x18\n\x10run_socks_length\x18` \x01(\r\x12\x0b\n\x03\x66\x39\x37\x18\x61 \x01(\r\x12\x19\n\x11ride_socks_length\x18\x62 \x01(\r\x12\x0b\n\x03\x66\x39\x39\x18\x63 \x01(\r\x12\x0c\n\x04\x66\x31\x30\x30\x18\x64 \x01(\r\x12\x0c\n\x04\x66\x31\x30\x31\x18\x65 \x01(\r\x12\x0c\n\x04\x66\x31\x30\x32\x18\x66 \x01(\r\x12\x0c\n\x04\x66\x31\x30\x33\x18g \x01(\r\x12\x0c\n\x04\x66\x31\x30\x34\x18h \x01(\r\x12\x1d\n\x15\x63onnected_to_withings\x18i \x01(\x08\x12\x1b\n\x13\x63onnected_to_fitbit\x18j \x01(\x08\x12\x1c\n\x14launched_game_client\x18l \x01(\t\x12\x1b\n\x13\x63urrent_activity_id\x18m \x01(\x03\x12\x1b\n\x13\x63onnected_to_garmin\x18n \x01(\x08\x12*\n\treminders\x18o \x03(\x0b\x32\x17.PlayerProfile.Reminder\x12\x0c\n\x04\x66\x31\x31\x32\x18p \x01(\x08\x12&\n\x12private_attributes\x18q \x03(\x0b\x32\n.Attribute\x12%\n\x11public_attributes\x18r \x03(\x0b\x32\n.Attribute\x12\x1a\n\x12total_run_calories\x18s \x01(\x05\x12\x0c\n\x04\x66\x31\x31\x36\x18t \x01(\x03\x12\x1f\n\x17run_time_1mi_in_seconds\x18u \x01(\x05\x12\x1f\n\x17run_time_5km_in_seconds\x18v \x01(\x05\x12 \n\x18run_time_10km_in_seconds\x18w \x01(\x05\x12)\n!run_time_half_marathon_in_seconds\x18x \x01(\x05\x12)\n!run_time_full_marathon_in_seconds\x18y \x01(\x05\x12\x0c\n\x04\x66\x31\x32\x32\x18z \x01(\x05\x12@\n\x14\x63ycling_organization\x18{ \x01(\x0e\x32\".PlayerProfile.CyclingOrganization\x12\x0c\n\x04\x66\x31\x32\x34\x18| \x01(\t\x12\x36\n\x18\x64\x65\x66\x61ult_activity_privacy\x18} \x01(\x0e\x32\x14.ActivityPrivacyType\x12\x1e\n\x16\x63onnected_to_runtastic\x18~ \x01(\x08\x12)\n\x10property_changes\x18\x7f \x03(\x0b\x32\x0f.PropertyChange\x1a\xa7\x02\n\x0bSocialFacts\x12\x12\n\nprofile_id\x18\x01 \x01(\x03\x12\x17\n\x0f\x66ollowers_count\x18\x02 \x01(\x05\x12\x17\n\x0f\x66ollowees_count\x18\x03 \x01(\x05\x12\x31\n)followees_in_common_with_logged_in_player\x18\x04 \x01(\x05\x12:\n#follower_status_of_logged_in_player\x18\x05 \x01(\x0e\x32\r.FollowStatus\x12:\n#followee_status_of_logged_in_player\x18\x06 \x01(\x0e\x32\r.FollowStatus\x12\'\n\x1fis_favorite_of_logged_in_player\x18\x07 \x01(\x08\x1a\x9c\x01\n\x08Reminder\x12\n\n\x02\x66\x31\x18\x01 \x01(\x03\x12\n\n\x02\x66\x32\x18\x02 \x01(\t\x12\n\n\x02\x66\x33\x18\x03 \x01(\x03\x12\x34\n\x02\x66\x34\x18\x04 \x03(\x0b\x32(.PlayerProfile.Reminder.ReminderProperty\x1a\x36\n\x10ReminderProperty\x12\n\n\x02\x66\x31\x18\x01 \x01(\x03\x12\n\n\x02\x66\x32\x18\x02 \x01(\t\x12\n\n\x02\x66\x33\x18\x03 \x01(\t\"|\n\x0f\x45nrolledProgram\x12\x14\n\x10\x45NROLLEDPROGRAM0\x10\x00\x12\x11\n\rZWIFT_ACADEMY\x10\x01\x12\x14\n\x10\x45NROLLEDPROGRAM2\x10\x02\x12\x14\n\x10\x45NROLLEDPROGRAM3\x10\x03\x12\x14\n\x10\x45NROLLEDPROGRAM4\x10\x04\"w\n\x13\x43yclingOrganization\x12\x16\n\x12NO_CYCLING_LICENSE\x10\x00\x12\x18\n\x14\x43YCLING_SOUTH_AFRICA\x10\x01\x12\x15\n\x11\x43YCLING_AUSTRALIA\x10\x02\x12\x17\n\x13\x43YCLING_NEW_ZEALAND\x10\x03\"2\n\x0ePlayerProfiles\x12 \n\x08profiles\x18\x01 \x03(\x0b\x32\x0e.PlayerProfile\"\xb0\x06\n\x12ProfileEntitlement\x12\x31\n\x04type\x18\x01 \x01(\x0e\x32#.ProfileEntitlement.EntitlementType\x12\n\n\x02id\x18\x02 \x01(\x03\x12<\n\x06status\x18\x03 \x01(\x0e\x32,.ProfileEntitlement.ProfileEntitlementStatus\x12\x0e\n\x06period\x18\x04 \x01(\t\x12\x17\n\x0f\x62\x65gin_time_unix\x18\x05 \x01(\r\x12\x15\n\rend_time_unix\x18\x06 \x01(\r\x12\x12\n\nkilometers\x18\x07 \x01(\r\x12\x1c\n\x14\x62\x65gin_total_distance\x18\x08 \x01(\r\x12\x1a\n\x12\x65nd_total_distance\x18\t \x01(\r\x12\x0e\n\x06source\x18\n \x01(\t\x12.\n\x08platform\x18\x0b \x01(\x0e\x32\x1c.ProfileEntitlement.Platform\x12\x19\n\x11renewal_date_unix\x18\x0c \x01(\r\x12\x18\n\x10new_trial_system\x18\r \x01(\x08\x12/\n\tplatforms\x18\x0e \x03(\x0e\x32\x1c.ProfileEntitlement.Platform\"L\n\x0f\x45ntitlementType\x12\x14\n\x10\x45NTITLEMENTTYPE0\x10\x00\x12\x08\n\x04RIDE\x10\x01\x12\x07\n\x03RUN\x10\x02\x12\x07\n\x03ROW\x10\x03\x12\x07\n\x03USE\x10\x04\"\x91\x01\n\x18ProfileEntitlementStatus\x12\x16\n\x12\x45NTITLEMENTSTATUS0\x10\x00\x12\x0b\n\x07\x45XPIRED\x10\x01\x12\n\n\x06\x41\x43TIVE\x10\x02\x12\x0c\n\x08\x43\x41NCELED\x10\x03\x12\x0c\n\x08INACTIVE\x10\x04\x12(\n$APPLIED_AS_SUBSCRIPTION_TRIAL_PERIOD\x10\x05\"\x86\x01\n\x08Platform\x12\x10\n\x0cPLATFORM_OSX\x10\x00\x12\x0f\n\x0bPLATFORM_PC\x10\x01\x12\x10\n\x0cPLATFORM_IOS\x10\x02\x12\x14\n\x10PLATFORM_ANDROID\x10\x03\x12\x11\n\rPLATFORM_TVOS\x10\x04\x12\r\n\tPLATFORM5\x10\x05\x12\r\n\tPLATFORM6\x10\x06\"\xcc\x02\n\x0cSubscription\x12&\n\x07gateway\x18\x01 \x01(\x0e\x32\x15.Subscription.Gateway\x12\x30\n\x06status\x18\x02 \x01(\x0e\x32 .Subscription.SubscriptionStatus\"#\n\x07Gateway\x12\r\n\tBRAINTREE\x10\x00\x12\t\n\x05\x41PPLE\x10\x01\"\xbc\x01\n\x12SubscriptionStatus\x12\x07\n\x03NEW\x10\x00\x12\x0b\n\x07\x45XPIRED\x10\x01\x12\n\n\x06\x41\x43TIVE\x10\x02\x12\x0c\n\x08\x43\x41NCELED\x10\x03\x12\x0c\n\x08PAST_DUE\x10\x04\x12\x0b\n\x07PENDING\x10\x05\x12\x0c\n\x08SUBERROR\x10\x06\x12\x10\n\x0cUNRECOGNIZED\x10\x07\x12\x0b\n\x07UNKNOWN\x10\x08\x12\x1f\n\x1b\x41\x43TIVE_WITH_PAYMENT_FAILURE\x10\t\x12\r\n\tABANDONED\x10\n\"\x96\x01\n\x0ePropertyChange\x12)\n\rproperty_name\x18\x01 \x02(\x0e\x32\x12.PropertyChange.Id\x12\x14\n\x0c\x63hange_count\x18\x02 \x01(\x05\x12\x13\n\x0bmax_changes\x18\x03 \x01(\x05\".\n\x02Id\x12\t\n\x05TYPE0\x10\x00\x12\x11\n\rDATE_OF_BIRTH\x10\x01\x12\n\n\x06GENDER\x10\x02\"X\n\tAttribute\x12\n\n\x02id\x18\x01 \x02(\x05\x12\x14\n\x0cnumber_value\x18\x02 \x01(\x03\x12\x13\n\x0b\x66loat_value\x18\x03 \x01(\x02\x12\x14\n\x0cstring_value\x18\x05 \x01(\t\"\x1e\n\x10\x41\x63hievementEntry\x12\n\n\x02id\x18\x01 \x02(\x05\"7\n\x0c\x41\x63hievements\x12\'\n\x0c\x61\x63hievements\x18\x01 \x03(\x0b\x32\x11.AchievementEntry\"6\n\x12\x42\x65stEffortPointMsg\x12\r\n\x05power\x18\x01 \x02(\x01\x12\x11\n\ttimestamp\x18\x02 \x01(\x04\"\x9b\x02\n\x18PowerCurveAggregationMsg\x12\x33\n\x05watts\x18\x01 \x03(\x0b\x32$.PowerCurveAggregationMsg.WattsEntry\x12?\n\x0cwatts_per_kg\x18\x02 \x03(\x0b\x32).PowerCurveAggregationMsg.WattsPerKgEntry\x1a\x41\n\nWattsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.BestEffortPointMsg:\x02\x38\x01\x1a\x46\n\x0fWattsPerKgEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.BestEffortPointMsg:\x02\x38\x01*;\n\x13\x41\x63tivityPrivacyType\x12\n\n\x06PUBLIC\x10\x00\x12\x0b\n\x07PRIVATE\x10\x01\x12\x0b\n\x07\x46RIENDS\x10\x02*E\n\x05Sport\x12\x0b\n\x07\x43YCLING\x10\x00\x12\x0b\n\x07RUNNING\x10\x01\x12\n\n\x06ROWING\x10\x02\x12\n\n\x06SPORT3\x10\x03\x12\n\n\x06SPORT4\x10\x04*\x9f\x01\n\nPlayerType\x12\x0f\n\x0bPLAYERTYPE0\x10\x00\x12\n\n\x06NORMAL\x10\x01\x12\x0f\n\x0bPRO_CYCLIST\x10\x02\x12\x0f\n\x0bZWIFT_STAFF\x10\x03\x12\x0e\n\nAMBASSADOR\x10\x04\x12\x0c\n\x08VERIFIED\x10\x05\x12\x07\n\x03ZED\x10\x06\x12\x07\n\x03ZAC\x10\x07\x12\x12\n\x0ePRO_TRIATHLETE\x10\x08\x12\x0e\n\nPRO_RUNNER\x10\t*B\n\tPowerType\x12\x17\n\nPT_UNKNOWN\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x12\x0e\n\nPT_VIRTUAL\x10\x00\x12\x0c\n\x08PT_METER\x10\x01*\x9e\x01\n\x0c\x46ollowStatus\x12\x11\n\rFOLLOWSTATUS0\x10\x00\x12\x0b\n\x07UNKNOWN\x10\x01\x12\x16\n\x12REQUESTS_TO_FOLLOW\x10\x02\x12\x10\n\x0cIS_FOLLOWING\x10\x03\x12\x15\n\x11HAS_BEEN_DECLINED\x10\x07\x12\x0e\n\nIS_BLOCKED\x10\x04\x12\x13\n\x0fNO_RELATIONSHIP\x10\x05\x12\x08\n\x04SELF\x10\x06') _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'profile_pb2', globals()) diff --git a/scripts/get_entitlements.py b/scripts/get_entitlements.py new file mode 100644 index 00000000..bc985c25 --- /dev/null +++ b/scripts/get_entitlements.py @@ -0,0 +1,21 @@ +import os +import xml.etree.ElementTree as ET +import json +import subprocess + +data = [] + +try: + if not os.path.isdir('global'): + os.makedirs('global') +except IOError as e: + print("failed to create dir 'global': %s" % str(e)) +os.chdir('global') +subprocess.run(['wad_unpack.exe', 'C:\\Program Files (x86)\\Zwift\\assets\\global.wad']) +tree = ET.parse('Entitlements.xml') +root = tree.getroot() +for entitlement in root.iter('Entitlement'): + data.append({'id': int(entitlement.get('id')), 'name': entitlement.get('name')}) + +with open('../../data/entitlements.txt', 'w') as f: + json.dump(data, f, indent=2) diff --git a/zwift_offline.py b/zwift_offline.py index b0ee296f..a22b8ff7 100644 --- a/zwift_offline.py +++ b/zwift_offline.py @@ -1752,13 +1752,23 @@ def do_api_profiles(profile_id, is_json): else: with open(profile_file, 'rb') as fd: profile.ParseFromString(fd.read()) - profile.id = profile_id - if not profile.email: - profile.email = 'user@email.com' - if profile.entitlements: - del profile.entitlements[:] - if not profile.mix_panel_distinct_id: - profile.mix_panel_distinct_id = str(uuid.uuid4()) + profile.id = profile_id + if not profile.email: + profile.email = 'user@email.com' + for entitlement in list(profile.entitlements): + if entitlement.type == profile_pb2.ProfileEntitlement.EntitlementType.RIDE: + profile.entitlements.remove(entitlement) + if os.path.isfile('%s/unlock_entitlements.txt' % STORAGE_DIR): + with open('%s/data/entitlements.txt' % SCRIPT_DIR) as f: + entitlements = json.load(f) + for entitlement in entitlements: + if not any(e.id == entitlement['id'] for e in profile.entitlements): + e = profile.entitlements.add() + e.type = profile_pb2.ProfileEntitlement.EntitlementType.USE + e.id = entitlement['id'] + e.status = profile_pb2.ProfileEntitlement.ProfileEntitlementStatus.ACTIVE + if not profile.mix_panel_distinct_id: + profile.mix_panel_distinct_id = str(uuid.uuid4()) if is_json: #todo: publicId, bodyType, totalRunCalories != total_watt_hours, totalRunTimeInMinutes != time_ridden_in_minutes etc if profile.dob != "": profile.age = age(datetime.datetime.strptime(profile.dob, "%m/%d/%Y"))