Line data Source code
1 : import 'package:matrix/matrix.dart';
2 :
3 : class FamedlyCallMemberEvent {
4 : final List<CallMembership> memberships;
5 :
6 2 : FamedlyCallMemberEvent({required this.memberships});
7 :
8 0 : Map<String, dynamic> toJson() {
9 0 : return {'memberships': memberships.map((e) => e.toJson()).toList()};
10 : }
11 :
12 2 : factory FamedlyCallMemberEvent.fromJson(Event event) {
13 2 : final List<CallMembership> callMemberships = [];
14 4 : final memberships = event.content.tryGetList('memberships');
15 2 : if (memberships != null && memberships.isNotEmpty) {
16 4 : for (final mem in memberships) {
17 2 : if (isValidMemEvent(mem)) {
18 : final callMem =
19 8 : CallMembership.fromJson(mem, event.senderId, event.room.id);
20 2 : if (callMem != null) callMemberships.add(callMem);
21 : }
22 : }
23 : }
24 2 : return FamedlyCallMemberEvent(memberships: callMemberships);
25 : }
26 : }
27 :
28 : class CallMembership {
29 : final String userId;
30 : final String callId;
31 : final String? application;
32 : final String? scope;
33 : final CallBackend backend;
34 : final String deviceId;
35 : final int expiresTs;
36 : final String membershipId;
37 : final List? feeds;
38 :
39 : final String roomId;
40 :
41 2 : CallMembership({
42 : required this.userId,
43 : required this.callId,
44 : required this.backend,
45 : required this.deviceId,
46 : required this.expiresTs,
47 : required this.roomId,
48 : required this.membershipId,
49 : this.application = 'm.call',
50 : this.scope = 'm.room',
51 : this.feeds,
52 : });
53 :
54 2 : Map<String, dynamic> toJson() {
55 2 : return {
56 4 : 'call_id': callId,
57 4 : 'application': application,
58 4 : 'scope': scope,
59 8 : 'foci_active': [backend.toJson()],
60 4 : 'device_id': deviceId,
61 4 : 'expires_ts': expiresTs,
62 2 : 'expires': 7200000, // element compatibiltiy remove asap
63 4 : 'membershipID': membershipId, // sessionId
64 2 : if (feeds != null) 'feeds': feeds,
65 : };
66 : }
67 :
68 2 : static CallMembership? fromJson(Map json, String userId, String roomId) {
69 : try {
70 2 : return CallMembership(
71 : userId: userId,
72 : roomId: roomId,
73 2 : callId: json['call_id'],
74 2 : application: json['application'],
75 2 : scope: json['scope'],
76 2 : backend: (json['foci_active'] as List)
77 6 : .map((e) => CallBackend.fromJson(e))
78 2 : .first,
79 2 : deviceId: json['device_id'],
80 2 : expiresTs: json['expires_ts'],
81 : membershipId:
82 2 : json['membershipID'] ?? 'someone_forgot_to_set_the_membershipID',
83 2 : feeds: json['feeds'],
84 : );
85 : } catch (e, s) {
86 0 : Logs().e('[VOIP] call membership parsing failed. $json', e, s);
87 : return null;
88 : }
89 : }
90 :
91 2 : @override
92 : bool operator ==(other) =>
93 : identical(this, other) ||
94 2 : other is CallMembership &&
95 6 : runtimeType == other.runtimeType &&
96 6 : userId == other.userId &&
97 0 : roomId == other.roomId &&
98 0 : callId == other.callId &&
99 0 : application == other.application &&
100 0 : scope == other.scope &&
101 0 : backend.type == other.backend.type &&
102 0 : deviceId == other.deviceId &&
103 0 : membershipId == other.membershipId;
104 :
105 0 : @override
106 0 : int get hashCode => Object.hash(
107 0 : userId.hashCode,
108 0 : roomId.hashCode,
109 0 : callId.hashCode,
110 0 : application.hashCode,
111 0 : scope.hashCode,
112 0 : backend.type.hashCode,
113 0 : deviceId.hashCode,
114 0 : membershipId.hashCode,
115 : );
116 :
117 : // with a buffer of 1 minute just incase we were slow to process a
118 : // call event, if the device is actually dead it should
119 : // get removed pretty soon
120 2 : bool get isExpired =>
121 4 : expiresTs <
122 2 : DateTime.now()
123 2 : .subtract(CallTimeouts.expireTsBumpDuration)
124 2 : .millisecondsSinceEpoch;
125 : }
|