mirror of
https://github.com/zoffline/zwift-offline.git
synced 2026-08-02 00:47:50 -07:00
meetups seems to be working now
This commit is contained in:
+47
-25
@@ -2,39 +2,44 @@ syntax = "proto2";
|
||||
import "profile.proto"; //enums PlayerType and Sport
|
||||
|
||||
message InvitedProfileProto {
|
||||
required uint64 ipp_f1 = 1;
|
||||
optional string ipp_f2 = 2;
|
||||
optional string ipp_f3 = 3;
|
||||
optional string ipp_f4 = 4;
|
||||
optional bool ipp_f5 = 5;
|
||||
optional bool ipp_f6 = 6;
|
||||
required uint64 player_id = 1;
|
||||
optional string firstName = 2;
|
||||
optional string lastName = 3;
|
||||
optional string imageSrc = 4;
|
||||
optional bool enrolledZwiftAcademy = 5;
|
||||
optional bool male = 6;
|
||||
optional PlayerType player_type = 7;
|
||||
}
|
||||
|
||||
enum EventInviteStatus {
|
||||
PENDING = 0;
|
||||
ACCEPTED = 1;
|
||||
REJECTED = 2;
|
||||
}
|
||||
message EventInviteProto {
|
||||
required InvitedProfileProto profile = 1;
|
||||
required uint64 invite_f2 = 2;
|
||||
optional InvitedProfileProto profile = 1;
|
||||
required EventInviteStatus status = 2;
|
||||
}
|
||||
|
||||
message PrivateEventFeedProto {
|
||||
required uint64 pef_f1 = 1; //read in PrivateEventsManagerV2::RegisterPrivateEvent
|
||||
required uint64 event_id = 1; //read in PrivateEventsManagerV2::RegisterPrivateEvent
|
||||
optional Sport sport = 2;
|
||||
optional uint64 eventSubgroupStart = 3; //IsPrivateEventExpired: return ZNETWORK_GetNetworkSyncedTimeGMT() > a1->m_eventSubgroupStart / 1000uLL + 1800
|
||||
optional uint64 route_id = 4;
|
||||
optional uint32 pef_f5 = 5;
|
||||
optional float pef_f6 = 6;
|
||||
optional uint64 pef_f7 = 7; //stored as int32
|
||||
optional uint32 pef_f8 = 8;
|
||||
optional uint32 pef_f9 = 9;
|
||||
optional uint32 pef_f10 = 10;
|
||||
optional string pef_f11 = 11;
|
||||
optional uint64 pef_f12 = 12;
|
||||
optional string pef_f13 = 13;
|
||||
optional string pef_f14 = 14;
|
||||
optional uint64 pef_f15 = 15;
|
||||
optional uint32 durationInSeconds = 5;
|
||||
optional float distanceInMeters = 6;
|
||||
optional uint64 answeredCount = 7; //stored as int32
|
||||
optional uint32 invitedTotalCount = 8;
|
||||
optional uint32 acceptedFolloweeCount = 9;
|
||||
optional uint32 acceptedTotalCount = 10;
|
||||
optional string organizerImageUrl = 11;
|
||||
optional uint64 organizerProfileId = 12;
|
||||
optional string organizerFirstName = 13;
|
||||
optional string organizerLastName = 14;
|
||||
optional uint64 updateDate = 15;
|
||||
optional uint64 subgroupId = 16;
|
||||
optional uint32 pef_f17 = 17;
|
||||
optional bool pef_f18 = 18;
|
||||
optional uint32 laps = 17;
|
||||
optional bool rubberbanding = 18; //keep together "rulesId": "1024"
|
||||
}
|
||||
|
||||
message PrivateEventFeedListProto {
|
||||
@@ -42,13 +47,13 @@ message PrivateEventFeedListProto {
|
||||
}
|
||||
|
||||
message PlayerJoinedEvent {
|
||||
required uint64 ev_sg_id = 1;
|
||||
required uint64 rel_id = 1; //subgroup id
|
||||
optional uint64 player_id = 2;
|
||||
optional uint64 pje_f3 = 3;
|
||||
}
|
||||
|
||||
message PlayerLeftEvent { //didn't decompiled yet, just a guess
|
||||
required uint64 ev_sg_id = 1;
|
||||
message PlayerLeftEvent {
|
||||
required uint64 rel_id = 1; //event id
|
||||
optional uint64 player_id = 2;
|
||||
optional uint64 ple_f3 = 3;
|
||||
}
|
||||
@@ -205,3 +210,20 @@ message Event { //real name: EventProtobuf; where is shortName, shortDescription
|
||||
message Events { //real name: EventsProtobuf
|
||||
repeated Event events = 1;
|
||||
}
|
||||
|
||||
message PrivateEventProto {
|
||||
required uint64 id = 1;
|
||||
optional Sport sport = 2;
|
||||
optional uint64 eventStart = 3;
|
||||
optional uint64 routeId = 4;
|
||||
optional uint64 startLocation = 5;
|
||||
optional uint32 durationInSeconds = 6;
|
||||
optional float distanceInMeters = 7;
|
||||
optional string description = 8;
|
||||
optional uint64 workoutHash = 9; //or laps
|
||||
optional uint64 organizerId = 10;
|
||||
repeated EventInviteProto eventInvites = 11;
|
||||
optional bool showResults = 12;
|
||||
optional uint32 laps = 13; //or workoutHash
|
||||
optional bool rubberbanding = 14;
|
||||
}
|
||||
+49
-32
File diff suppressed because one or more lines are too long
@@ -249,6 +249,7 @@
|
||||
},
|
||||
{
|
||||
"name": "game_1_20_home_screen",
|
||||
"value": true,
|
||||
"values": {}
|
||||
},
|
||||
{
|
||||
|
||||
+180
-91
@@ -207,10 +207,23 @@ class AnonUser(User, AnonymousUserMixin, db.Model):
|
||||
return True
|
||||
|
||||
class PartialProfile:
|
||||
player_id = 0
|
||||
first_name = ''
|
||||
last_name = ''
|
||||
country_code = 0
|
||||
route = 0
|
||||
player_type = 'NORMAL'
|
||||
male = True
|
||||
imageSrc = ''
|
||||
def to_json(self):
|
||||
return {"countryCode": self.country_code,
|
||||
"enrolledZwiftAcademy": False, #don't need
|
||||
"firstName": self.first_name,
|
||||
"id": self.player_id,
|
||||
"imageSrc": self.imageSrc,
|
||||
"lastName": self.last_name,
|
||||
"male": self.male,
|
||||
"playerType": self.player_type }
|
||||
|
||||
class Online:
|
||||
total = 0
|
||||
@@ -312,9 +325,13 @@ def get_partial_profile(player_id):
|
||||
profile = profile_pb2.PlayerProfile()
|
||||
profile.ParseFromString(fd.read())
|
||||
partial_profile = PartialProfile()
|
||||
partial_profile.player_id = player_id
|
||||
partial_profile.imageSrc = "https://us-or-rly101.zwift.com/download/%s/avatarLarge.jpg" % player_id
|
||||
partial_profile.first_name = profile.first_name
|
||||
partial_profile.last_name = profile.last_name
|
||||
partial_profile.country_code = profile.country_code
|
||||
partial_profile.player_type = profile_pb2.PlayerType.Name(jsf(profile, 'player_type', 1))
|
||||
partial_profile.male = profile.is_male
|
||||
for f in profile.public_attributes:
|
||||
#0x69520F20=1766985504 - crc32 of "PACE PARTNER - ROUTE"
|
||||
#TODO: -1021012238: figure out
|
||||
@@ -653,6 +670,11 @@ def user_home(username):
|
||||
return render_template("user_home.html", username=current_user.username, enable_ghosts=bool(current_user.enable_ghosts),
|
||||
online=get_online(), is_admin=current_user.is_admin, restarting=restarting, restarting_in_minutes=restarting_in_minutes, server_ip=os.path.exists(SERVER_IP_FILE))
|
||||
|
||||
def enqueue_player_update(player_id, wa_bytes):
|
||||
if not player_id in player_update_queue:
|
||||
player_update_queue[player_id] = list()
|
||||
player_update_queue[player_id].append(wa_bytes)
|
||||
|
||||
def send_message_to_all_online(message, sender='Server'):
|
||||
player_update = udp_node_msgs_pb2.WorldAttribute()
|
||||
player_update.server_realm = udp_node_msgs_pb2.ZofflineConstants.RealmID
|
||||
@@ -672,11 +694,9 @@ def send_message_to_all_online(message, sender='Server'):
|
||||
chat_message.countryCode = 0
|
||||
|
||||
player_update.payload = chat_message.SerializeToString()
|
||||
|
||||
for recieving_player_id in online.keys():
|
||||
if not recieving_player_id in player_update_queue:
|
||||
player_update_queue[recieving_player_id] = list()
|
||||
player_update_queue[recieving_player_id].append(player_update.SerializeToString())
|
||||
player_update_s = player_update.SerializeToString()
|
||||
for receiving_player_id in online.keys():
|
||||
enqueue_player_update(receiving_player_id, player_update_s)
|
||||
|
||||
|
||||
def send_restarting_message():
|
||||
@@ -922,7 +942,7 @@ def activity_moving_time(activity):
|
||||
def activity_protobuf_to_json(activity):
|
||||
profile = get_partial_profile(activity.player_id)
|
||||
return {"id":activity.id,"profile":{"id":str(activity.player_id),"firstName":profile.first_name,"lastName":profile.last_name, \
|
||||
"imageSrc":"https://us-or-rly101.zwift.com/download/%s/avatarLarge.jpg" % activity.player_id,"approvalRequired":None}, \
|
||||
"imageSrc":profile.imageSrc,"approvalRequired":None}, \
|
||||
"worldId":activity.f3,"name":activity.name,"sport":str_sport(activity.f29),"startDate":activity.start_date, \
|
||||
"endDate":activity.end_date,"distanceInMeters":activity.distance, \
|
||||
"totalElevation":activity.total_elevation,"calories":activity.calories,"primaryImageUrl":"", \
|
||||
@@ -1141,11 +1161,29 @@ def api_events_search():
|
||||
else:
|
||||
return events.SerializeToString(), 200
|
||||
|
||||
@app.route('/api/events/subgroups/signup/<int:event_id>', methods=['POST'])
|
||||
@app.route('/api/events/signup/<int:event_id>', methods=['DELETE'])
|
||||
def create_event_wat(rel_id, wa_type, pe, dest_ids):
|
||||
player_update = udp_node_msgs_pb2.WorldAttribute()
|
||||
player_update.server_realm = udp_node_msgs_pb2.ZofflineConstants.RealmID
|
||||
player_update.wa_type = wa_type
|
||||
player_update.world_time_born = world_time()
|
||||
player_update.world_time_expire = world_time() + 60000
|
||||
player_update.wa_f12 = 1
|
||||
player_update.timestamp = int(get_utc_time()*1000000)
|
||||
player_update.rel_id = current_user.player_id
|
||||
|
||||
pe.rel_id = rel_id
|
||||
pe.player_id = current_user.player_id
|
||||
#optional uint64 pje_f3/ple_f3 = 3;
|
||||
player_update.payload = pe.SerializeToString()
|
||||
|
||||
for receiving_player_id in dest_ids:
|
||||
enqueue_player_update(receiving_player_id, player_update_s)
|
||||
|
||||
@app.route('/api/events/subgroups/signup/<int:rel_id>', methods=['POST'])
|
||||
@app.route('/api/events/signup/<int:rel_id>', methods=['DELETE'])
|
||||
@jwt_to_session_cookie
|
||||
@login_required
|
||||
def api_events_subgroups_signup_id(event_id):
|
||||
def api_events_subgroups_signup_id(rel_id):
|
||||
if request.method == 'POST':
|
||||
wa_type = udp_node_msgs_pb2.WA_TYPE.WAT_JOIN_E
|
||||
pe = events_pb2.PlayerJoinedEvent()
|
||||
@@ -1155,42 +1193,24 @@ def api_events_subgroups_signup_id(event_id):
|
||||
pe = events_pb2.PlayerLeftEvent()
|
||||
ret = False
|
||||
#empty request.data
|
||||
player_update = udp_node_msgs_pb2.WorldAttribute()
|
||||
player_update.server_realm = udp_node_msgs_pb2.ZofflineConstants.RealmID
|
||||
player_update.wa_type = wa_type
|
||||
player_update.world_time_born = world_time()
|
||||
player_update.world_time_expire = world_time() + 60000
|
||||
player_update.wa_f12 = 1
|
||||
player_update.timestamp = int(get_utc_time()*1000000)
|
||||
|
||||
pe.ev_sg_id = event_id
|
||||
pe.player_id = current_user.player_id
|
||||
#optional uint64 pje_f3/ple_f3 = 3;
|
||||
player_update.payload = pe.SerializeToString()
|
||||
|
||||
for recieving_player_id in online.keys():
|
||||
if not recieving_player_id in player_update_queue:
|
||||
player_update_queue[recieving_player_id] = list()
|
||||
player_update_queue[recieving_player_id].append(player_update.SerializeToString())
|
||||
|
||||
create_event_wat(rel_id, wa_type, pe, online.keys())
|
||||
return jsonify({"signedUp":ret})
|
||||
|
||||
|
||||
@app.route('/api/events/subgroups/register/<int:event_id>', methods=['POST'])
|
||||
def api_events_subgroups_register_id(event_id):
|
||||
@app.route('/api/events/subgroups/register/<int:ev_sg_id>', methods=['POST'])
|
||||
def api_events_subgroups_register_id(ev_sg_id):
|
||||
return '{"registered":true}', 200
|
||||
|
||||
|
||||
@app.route('/api/events/subgroups/entrants/<int:event_id>', methods=['GET'])
|
||||
def api_events_subgroups_entrants_id(event_id):
|
||||
@app.route('/api/events/subgroups/entrants/<int:ev_sg_id>', methods=['GET'])
|
||||
def api_events_subgroups_entrants_id(ev_sg_id):
|
||||
return '[]', 200
|
||||
|
||||
@app.route('/api/events/subgroups/invited_ride_sweepers/<int:event_id>', methods=['GET'])
|
||||
def api_events_subgroups_invited_ride_sweepers_id(event_id):
|
||||
@app.route('/api/events/subgroups/invited_ride_sweepers/<int:ev_sg_id>', methods=['GET'])
|
||||
def api_events_subgroups_invited_ride_sweepers_id(ev_sg_id):
|
||||
return '[]', 200
|
||||
|
||||
@app.route('/api/events/subgroups/invited_ride_leaders/<int:event_id>', methods=['GET'])
|
||||
def api_events_subgroups_invited_ride_leaders_id(event_id):
|
||||
@app.route('/api/events/subgroups/invited_ride_leaders/<int:ev_sg_id>', methods=['GET'])
|
||||
def api_events_subgroups_invited_ride_leaders_id(ev_sg_id):
|
||||
return '[]', 200
|
||||
|
||||
@app.route('/relay/race/event_starting_line/<int:event_id>', methods=['POST'])
|
||||
@@ -1856,10 +1876,10 @@ def api_profiles_activities_id(player_id, activity_id):
|
||||
zwift_upload(player_id, activity)
|
||||
return response, 200
|
||||
|
||||
@app.route('/api/profiles/<int:recieving_player_id>/activities/0/rideon', methods=['POST']) #activity_id Seem to always be 0, even when giving ride on to ppl with 30km+
|
||||
@app.route('/api/profiles/<int:receiving_player_id>/activities/0/rideon', methods=['POST']) #activity_id Seem to always be 0, even when giving ride on to ppl with 30km+
|
||||
@jwt_to_session_cookie
|
||||
@login_required
|
||||
def api_profiles_activities_rideon(recieving_player_id):
|
||||
def api_profiles_activities_rideon(receiving_player_id):
|
||||
sending_player_id = request.json['profileId']
|
||||
profile = get_partial_profile(sending_player_id)
|
||||
if not profile == None:
|
||||
@@ -1872,22 +1892,24 @@ def api_profiles_activities_rideon(recieving_player_id):
|
||||
|
||||
ride_on = udp_node_msgs_pb2.RideOn()
|
||||
ride_on.player_id = int(sending_player_id)
|
||||
ride_on.to_player_id = int(recieving_player_id)
|
||||
ride_on.to_player_id = int(receiving_player_id)
|
||||
ride_on.firstName = profile.first_name
|
||||
ride_on.lastName = profile.last_name
|
||||
ride_on.countryCode = profile.country_code
|
||||
|
||||
player_update.payload = ride_on.SerializeToString()
|
||||
|
||||
if not recieving_player_id in player_update_queue:
|
||||
player_update_queue[recieving_player_id] = list()
|
||||
player_update_queue[recieving_player_id].append(player_update.SerializeToString())
|
||||
enqueue_player_update(receiving_player_id, player_update.SerializeToString())
|
||||
|
||||
receiver = get_partial_profile(recieving_player_id)
|
||||
receiver = get_partial_profile(receiving_player_id)
|
||||
message = 'Ride on ' + receiver.first_name + ' ' + receiver.last_name + '!'
|
||||
discord.send_message(message, sending_player_id)
|
||||
return '{}', 200
|
||||
|
||||
def stime_to_timestamp(stime):
|
||||
utc_offset = datetime.datetime.fromtimestamp(0) - datetime.datetime.utcfromtimestamp(0)
|
||||
return int((datetime.datetime.strptime(stime, '%Y-%m-%dT%H:%M:%SZ') + utc_offset).timestamp())
|
||||
|
||||
glb_notifications = {} #player_id -> dictionary, todo: move to database
|
||||
glb_cur_notif_id = 1
|
||||
def create_zca_notification(player_id, private_event, organizer):
|
||||
@@ -1895,9 +1917,8 @@ def create_zca_notification(player_id, private_event, organizer):
|
||||
if not player_id in glb_notifications.keys():
|
||||
glb_notifications[player_id] = {}
|
||||
d = glb_notifications[player_id]
|
||||
utc_offset = datetime.datetime.fromtimestamp(0) - datetime.datetime.utcfromtimestamp(0)
|
||||
argString0 = json.dumps({"eventId":private_event['id'],"eventStartDate": \
|
||||
int((datetime.datetime.strptime(private_event['eventStart'], '%Y-%m-%dT%H:%M:%SZ') + utc_offset).timestamp()), \
|
||||
stime_to_timestamp(private_event['eventStart']), \
|
||||
"otherInviteeCount":len(private_event['invitedProfileIds'])})
|
||||
n = { "activity": None, "argLong0": 0, "argLong1": 0, "argString0": argString0,
|
||||
"createdOn": str_timestamp(unix_time_millis(datetime.datetime.now())),
|
||||
@@ -1964,13 +1985,13 @@ def edit_private_event(player_id, meetup_id, decision):
|
||||
@app.route('/api/private_event/<int:meetup_id>/accept', methods=['PUT'])
|
||||
@jwt_to_session_cookie
|
||||
@login_required
|
||||
def api_private_event_accept(meetup_id): #todo: check if world attribute sent
|
||||
def api_private_event_accept(meetup_id):
|
||||
return edit_private_event(current_user.player_id, meetup_id, 'ACCEPTED')
|
||||
|
||||
@app.route('/api/private_event/<int:meetup_id>/reject', methods=['PUT'])
|
||||
@jwt_to_session_cookie
|
||||
@login_required
|
||||
def api_private_event_reject(meetup_id): #todo: check if world attribute sent
|
||||
def api_private_event_reject(meetup_id):
|
||||
return edit_private_event(current_user.player_id, meetup_id, 'REJECTED')
|
||||
|
||||
@app.route('/api/private_event/<int:meetup_id>', methods=['PUT'])
|
||||
@@ -1992,6 +2013,11 @@ def api_private_event_edit(meetup_id):
|
||||
n['lastModified'] = org_json_pe['updateDate']
|
||||
return jsonify({"id":meetup_id})
|
||||
|
||||
def enqueue_wa_event_invites(player_id, wa):
|
||||
for wat in (udp_node_msgs_pb2.WA_TYPE.WAT_EVENT, udp_node_msgs_pb2.WA_TYPE.WAT_INV_W):
|
||||
wa.wa_type = wat
|
||||
enqueue_player_update(player_id, wa.SerializeToString())
|
||||
|
||||
@app.route('/api/private_event', methods=['POST'])
|
||||
@jwt_to_session_cookie
|
||||
@login_required
|
||||
@@ -2006,57 +2032,64 @@ def api_private_event_new(): #{"culling":true,"description":"mesg","distanceInMe
|
||||
json_pe['eventSubgroupId'] = pe_id + 2
|
||||
json_pe['name'] = "Route #%s" % json_pe['routeId'] #todo: more readable
|
||||
json_pe['acceptedTotalCount'] = len(json_pe['invitedProfileIds']) #todo: real count
|
||||
json_pe['acceptedFolloweeCount'] = len(json_pe['invitedProfileIds']) #todo: real count
|
||||
json_pe['invitedTotalCount'] = len(json_pe['invitedProfileIds'])
|
||||
json_pe['acceptedFolloweeCount'] = len(json_pe['invitedProfileIds']) + 1 #todo: real count
|
||||
json_pe['invitedTotalCount'] = len(json_pe['invitedProfileIds']) + 1
|
||||
partial_profile = get_partial_profile(current_user.player_id)
|
||||
json_pe['organizerProfileId'] = current_user.player_id
|
||||
json_pe['organizerId'] = current_user.player_id
|
||||
json_pe['startLocation'] = 1 #todo_pe
|
||||
json_pe['allowsLateJoin'] = True #todo_pe
|
||||
json_pe['organizerFirstName'] = partial_profile.first_name
|
||||
json_pe['organizerLastName'] = partial_profile.last_name
|
||||
json_pe['updateDate'] = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
json_pe['organizerImageUrl'] = "https://us-or-rly101.zwift.com/download/%s/avatarLarge.jpg" % current_user.player_id
|
||||
eventInvites = [{"invitedProfile": {
|
||||
"countryCode": partial_profile.country_code,
|
||||
"enrolledZwiftAcademy": False, #todo
|
||||
"firstName": partial_profile.first_name,
|
||||
"id": current_user.player_id,
|
||||
"imageSrc": json_pe['organizerImageUrl'],
|
||||
"lastName": partial_profile.last_name,
|
||||
"male": True, #todo
|
||||
"playerType": "NORMAL", #todo
|
||||
},
|
||||
"status": "ACCEPTED"}]
|
||||
eventInvites = [{"invitedProfile": partial_profile.to_json(), "status": "ACCEPTED"}]
|
||||
create_event_wat(ev_sg_id, udp_node_msgs_pb2.WA_TYPE.WAT_JOIN_E, events_pb2.PlayerJoinedEvent(), online.keys())
|
||||
|
||||
pe = events_pb2.EventInviteProto()
|
||||
pe = events_pb2.Event()
|
||||
player_update = udp_node_msgs_pb2.WorldAttribute()
|
||||
player_update.server_realm = udp_node_msgs_pb2.ZofflineConstants.RealmID
|
||||
player_update.wa_type = udp_node_msgs_pb2.WA_TYPE.WAT_INV_W
|
||||
player_update.world_time_born = world_time()
|
||||
player_update.world_time_expire = world_time() + 60000
|
||||
player_update.wa_f12 = 1
|
||||
player_update.timestamp = int(get_utc_time()*1000000)
|
||||
|
||||
pe.invite_f2 = 1
|
||||
pe.id = pe_id
|
||||
pe.server_realm = udp_node_msgs_pb2.ZofflineConstants.RealmID
|
||||
pe.name = json_pe['name']
|
||||
if 'description' in json_pe:
|
||||
pe.description = json_pe['description']
|
||||
pe.eventStart = stime_to_timestamp(json_pe['eventStart'])*1000
|
||||
pe.distanceInMeters = json_pe['distanceInMeters']
|
||||
pe.laps = json_pe['laps']
|
||||
if 'imageUrl' in json_pe:
|
||||
pe.imageUrl = json_pe['imageUrl']
|
||||
pe.durationInSeconds = json_pe['durationInSeconds']
|
||||
pe.route_id = json_pe['routeId']
|
||||
#{"rubberbanding":true,"showResults":false,"workoutHash":0} todo_pe
|
||||
pe.visible = True
|
||||
pe.jerseyHash = 0
|
||||
pe.sport = sport_from_str(json_pe['sport'])
|
||||
#pe.uint64 e_f23 = 23; =0
|
||||
pe.eventType = events_pb2.EventType.EFONDO
|
||||
if 'culling' in json_pe:
|
||||
if json_pe['culling']:
|
||||
pe.eventType = events_pb2.EventType.RACE
|
||||
#pe.uint64 e_f25 = 25; =0
|
||||
pe.e_f27 = 2 #<=4, ENUM? saw = 2
|
||||
#pe.bool overrideMapPreferences = 28; =0
|
||||
#pe.bool invisibleToNonParticipants = 29; =0 todo_pe
|
||||
pe.lateJoinInMinutes = 30 #todo_pe
|
||||
#pe.course_id = 1 #todo_pe =f(json_pe['routeId']) ???
|
||||
player_update.payload = pe.SerializeToString()
|
||||
player_update_s = player_update.SerializeToString()
|
||||
enqueue_wa_event_invites(current_user.player_id, player_update)
|
||||
|
||||
for peer_id in json_pe['invitedProfileIds']:
|
||||
create_zca_notification(peer_id, json_pe, eventInvites[0]["invitedProfile"])
|
||||
if not peer_id in player_update_queue:
|
||||
player_update_queue[peer_id] = list()
|
||||
player_update_queue[peer_id].append(player_update_s)
|
||||
player_update.rel_id = peer_id
|
||||
enqueue_wa_event_invites(peer_id, player_update)
|
||||
p_partial_profile = get_partial_profile(peer_id)
|
||||
eventInvites.append({"invitedProfile": {
|
||||
"countryCode": p_partial_profile.country_code,
|
||||
"enrolledZwiftAcademy": False, #todo
|
||||
"firstName": p_partial_profile.first_name,
|
||||
"id": peer_id,
|
||||
"imageSrc": "https://us-or-rly101.zwift.com/download/%s/avatarLarge.jpg" % peer_id,
|
||||
"lastName": p_partial_profile.last_name,
|
||||
"male": True, #todo
|
||||
"playerType": "NORMAL", #todo
|
||||
},
|
||||
"status": "PENDING"})
|
||||
eventInvites.append({"invitedProfile": p_partial_profile.to_json(), "status": "PENDING"})
|
||||
json_pe['eventInvites'] = eventInvites
|
||||
|
||||
glb_private_events[pe_id] = json_pe
|
||||
@@ -2076,7 +2109,33 @@ def clone_and_append_social(player_id, private_event):
|
||||
ret['inviteStatus'] = status
|
||||
return ret
|
||||
|
||||
@app.route('/api/private_event/feed', methods=['GET', 'POST'])
|
||||
def jsonPrivateEventFeedToProtobuf(jfeed):
|
||||
ret = events_pb2.PrivateEventFeedListProto()
|
||||
#print(jfeed)
|
||||
for jpef in jfeed:
|
||||
pef = ret.pef.add()
|
||||
pef.event_id = jpef['id']
|
||||
pef.sport = sport_from_str(jpef['sport'])
|
||||
pef.eventSubgroupStart = stime_to_timestamp(jpef['eventStart'])*1000
|
||||
pef.route_id = jpef['routeId']
|
||||
pef.durationInSeconds = jpef['durationInSeconds']
|
||||
pef.distanceInMeters = jpef['distanceInMeters']
|
||||
pef.answeredCount = 1 #todo
|
||||
pef.invitedTotalCount = jpef['invitedTotalCount']
|
||||
pef.acceptedFolloweeCount = jpef['acceptedFolloweeCount']
|
||||
pef.acceptedTotalCount = jpef['acceptedTotalCount']
|
||||
pef.organizerImageUrl = jpef['organizerImageUrl']
|
||||
pef.organizerProfileId = jpef['organizerProfileId']
|
||||
pef.organizerFirstName = jpef['organizerFirstName']
|
||||
pef.organizerLastName = jpef['organizerLastName']
|
||||
pef.updateDate = stime_to_timestamp(jpef['updateDate'])*1000
|
||||
pef.subgroupId = jpef['eventSubgroupId']
|
||||
pef.laps = jpef['laps']
|
||||
pef.rubberbanding = jpef['rubberbanding']
|
||||
#print(ret)
|
||||
return ret
|
||||
|
||||
@app.route('/api/private_event/feed', methods=['GET'])
|
||||
@jwt_to_session_cookie
|
||||
@login_required
|
||||
def api_private_event_feed():
|
||||
@@ -2084,7 +2143,39 @@ def api_private_event_feed():
|
||||
for pe in glb_private_events.values():
|
||||
ret.append(clone_and_append_social(current_user.player_id, pe))
|
||||
#print(ret)
|
||||
return jsonify(ret)
|
||||
if(request.headers['Accept'] == 'application/json'):
|
||||
return jsonify(ret)
|
||||
return jsonPrivateEventFeedToProtobuf(ret).SerializeToString(), 200
|
||||
|
||||
def jsonPrivateEventToProtobuf(je):
|
||||
ret = events_pb2.PrivateEventProto()
|
||||
ret.id = je['id']
|
||||
ret.sport = sport_from_str(je['sport'])
|
||||
ret.eventStart = stime_to_timestamp(je['eventStart'])*1000
|
||||
ret.routeId = je['routeId']
|
||||
ret.startLocation = je['startLocation']
|
||||
ret.durationInSeconds = je['durationInSeconds']
|
||||
ret.distanceInMeters = je['distanceInMeters']
|
||||
if 'description' in je:
|
||||
ret.description = je['description']
|
||||
ret.workoutHash = je['workoutHash']
|
||||
ret.organizerId = je['organizerProfileId']
|
||||
for jinv in je['eventInvites']:
|
||||
jp = jinv['invitedProfile']
|
||||
inv = ret.eventInvites.add()
|
||||
inv.profile.player_id = jp['id']
|
||||
inv.profile.firstName = jp['firstName']
|
||||
inv.profile.lastName = jp['lastName']
|
||||
inv.profile.imageSrc = jp['imageSrc']
|
||||
inv.profile.enrolledZwiftAcademy = jp['enrolledZwiftAcademy']
|
||||
inv.profile.male = jp['male']
|
||||
inv.profile.player_type = profile_pb2.PlayerType.Value(jp['playerType'])
|
||||
inv.status = events_pb2.EventInviteStatus.Value(jinv['status'])
|
||||
ret.showResults = je['showResults']
|
||||
ret.laps = je['laps']
|
||||
ret.rubberbanding = je['rubberbanding']
|
||||
#print(je)
|
||||
return ret
|
||||
|
||||
@app.route('/api/private_event/<int:event_id>', methods=['GET'])
|
||||
@jwt_to_session_cookie
|
||||
@@ -2092,7 +2183,9 @@ def api_private_event_feed():
|
||||
def api_private_event_id(event_id):
|
||||
ret = clone_and_append_social(current_user.player_id, glb_private_events[event_id])
|
||||
#print(ret)
|
||||
return jsonify(ret)
|
||||
if(request.headers['Accept'] == 'application/json'):
|
||||
return jsonify(ret)
|
||||
return jsonPrivateEventToProtobuf(ret).SerializeToString(), 200
|
||||
|
||||
@app.route('/api/private_event/entitlement', methods=['GET'])
|
||||
def api_private_event_entitlement():
|
||||
@@ -2361,10 +2454,10 @@ def relay_worlds_generic(server_realm=None):
|
||||
player_update.world_time_expire = world_time() + 60000
|
||||
player_update.wa_f12 = 1
|
||||
player_update.timestamp = int(get_utc_time()*1000000)
|
||||
for recieving_player_id in online.keys():
|
||||
for receiving_player_id in online.keys():
|
||||
should_receive = False
|
||||
if player_update.wa_type == udp_node_msgs_pb2.WA_TYPE.WAT_SPA or player_update.wa_type == udp_node_msgs_pb2.WA_TYPE.WAT_SR:
|
||||
recieving_player = online[recieving_player_id]
|
||||
receiving_player = online[receiving_player_id]
|
||||
#Chat message
|
||||
if player_update.wa_type == udp_node_msgs_pb2.WA_TYPE.WAT_SPA:
|
||||
chat_message = tcp_node_msgs_pb2.SocialPlayerAction()
|
||||
@@ -2373,7 +2466,7 @@ def relay_worlds_generic(server_realm=None):
|
||||
if sending_player_id in online:
|
||||
sending_player = online[sending_player_id]
|
||||
#Check that players are on same course and close to each other
|
||||
if is_nearby(sending_player, recieving_player):
|
||||
if is_nearby(sending_player, receiving_player):
|
||||
should_receive = True
|
||||
#Segment complete
|
||||
else:
|
||||
@@ -2383,15 +2476,13 @@ def relay_worlds_generic(server_realm=None):
|
||||
if sending_player_id in online:
|
||||
sending_player = online[sending_player_id]
|
||||
#Check that players are on same course
|
||||
if get_course(sending_player) == get_course(recieving_player) or recieving_player.watchingRiderId == sending_player_id:
|
||||
if get_course(sending_player) == get_course(receiving_player) or receiving_player.watchingRiderId == sending_player_id:
|
||||
should_receive = True
|
||||
#Other PlayerUpdate, send to all
|
||||
else:
|
||||
should_receive = True
|
||||
if should_receive:
|
||||
if not recieving_player_id in player_update_queue:
|
||||
player_update_queue[recieving_player_id] = list()
|
||||
player_update_queue[recieving_player_id].append(player_update.SerializeToString())
|
||||
enqueue_player_update(receiving_player_id, player_update.SerializeToString())
|
||||
if player_update.wa_type == udp_node_msgs_pb2.WA_TYPE.WAT_SPA:
|
||||
chat_message = tcp_node_msgs_pb2.SocialPlayerAction()
|
||||
chat_message.ParseFromString(player_update.payload)
|
||||
@@ -2601,9 +2692,7 @@ def relay_worlds_attributes():
|
||||
else:
|
||||
should_receive = True
|
||||
if should_receive:
|
||||
if not receiving_player_id in player_update_queue:
|
||||
player_update_queue[receiving_player_id] = list()
|
||||
player_update_queue[receiving_player_id].append(player_update.SerializeToString())
|
||||
enqueue_player_update(receiving_player_id, player_update.SerializeToString())
|
||||
# If it's a chat message, send to Discord
|
||||
if player_update.wa_type == udp_node_msgs_pb2.WA_TYPE.WAT_SPA:
|
||||
chat_message = tcp_node_msgs_pb2.SocialPlayerAction()
|
||||
|
||||
Reference in New Issue
Block a user