add api endpoint to fetch call info
This commit is contained in:
@@ -21,7 +21,7 @@
|
||||
<body class="bg-gray-100">
|
||||
<div id="app" class="flex h-full">
|
||||
|
||||
<div class="mx-auto my-auto w-full max-w-lg p-4">
|
||||
<div class="mx-auto my-auto w-full max-w-xl p-4">
|
||||
|
||||
<!-- in active call -->
|
||||
<div v-if="isWebsocketConnected" class="w-full">
|
||||
@@ -38,7 +38,25 @@
|
||||
|
||||
<div class="mb-2">
|
||||
<div class="mb-1 text-sm font-medium text-gray-900">Call Hash</div>
|
||||
<div class="text-xs text-gray-600">{{ callHash }}</div>
|
||||
<div class="text-xs text-gray-600">{{ audioCall?.hash || "Unknown" }}</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<div class="mb-1 text-sm font-medium text-gray-900">Remote Identity Hash</div>
|
||||
<div class="text-xs text-gray-600">{{ audioCall?.remote_identity_hash || "Unknown" }}</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<div class="mb-1 text-sm font-medium text-gray-900">Remote Destination Hash</div>
|
||||
<div class="text-xs text-gray-600">{{ audioCall?.remote_destination_hash || "Unknown" }}</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<div class="mb-1 text-sm font-medium text-gray-900">Path</div>
|
||||
<div class="text-xs text-gray-600">
|
||||
<span v-if="audioCall?.path">{{ audioCall.path.hops }} {{ audioCall.path.hops === 1 ? 'hop' : 'hops' }} away via {{ audioCall.path.next_hop_interface }}</span>
|
||||
<span v-else>Unknown</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
@@ -118,11 +136,12 @@
|
||||
</div>
|
||||
<div class="my-auto">Active Calls</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="divide-y">
|
||||
<div v-for="audioCall in activeAudioCalls" class="flex p-2">
|
||||
<div>
|
||||
<div>Call Hash: {{ audioCall.hash }}</div>
|
||||
<div v-if="!audioCall.is_outbound">Initiator Identity: {{ audioCall.initiator_identity_hash || "Unknown" }}</div>
|
||||
<div>Identity: {{ audioCall.remote_identity_hash || "Unknown" }}</div>
|
||||
<div>Destination: {{ audioCall.remote_destination_hash || "Unknown" }}</div>
|
||||
<div>
|
||||
<span v-if="audioCall.is_outbound">Direction: Outbound</span>
|
||||
<span v-else>Direction: Inbound</span>
|
||||
@@ -159,11 +178,12 @@
|
||||
</div>
|
||||
<div class="my-auto">Call History</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="divide-y">
|
||||
<div v-for="audioCall in inactiveAudioCalls" class="flex p-2">
|
||||
<div>
|
||||
<div>Call Hash: {{ audioCall.hash }}</div>
|
||||
<div v-if="!audioCall.is_outbound">Initiator Identity: {{ audioCall.initiator_identity_hash || "Unknown" }}</div>
|
||||
<div>Identity: {{ audioCall.remote_identity_hash || "Unknown" }}</div>
|
||||
<div>Destination: {{ audioCall.remote_destination_hash || "Unknown" }}</div>
|
||||
<div>
|
||||
<span v-if="audioCall.is_outbound">Direction: Outbound</span>
|
||||
<span v-else>Direction: Inbound</span>
|
||||
@@ -201,6 +221,7 @@
|
||||
data() {
|
||||
return {
|
||||
|
||||
audioCall: null,
|
||||
audioCalls: [],
|
||||
|
||||
myAudioCallAddressHash: null,
|
||||
@@ -313,6 +334,8 @@
|
||||
// we are now connected
|
||||
this.isWebsocketConnected = true;
|
||||
|
||||
await this.updateCall(callHash);
|
||||
|
||||
// send mic audio over call
|
||||
await this.startRecordingMicrophone((encoded) => {
|
||||
|
||||
@@ -543,6 +566,24 @@
|
||||
// do nothing on error
|
||||
}
|
||||
},
|
||||
async updateCall(callHash) {
|
||||
|
||||
// clear previous call
|
||||
this.audioCall = null;
|
||||
|
||||
try {
|
||||
|
||||
// get path to destination
|
||||
const response = await window.axios.get(`/api/v1/calls/${callHash}`);
|
||||
|
||||
// update ui
|
||||
this.audioCall = response.data.audio_call;
|
||||
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
activeAudioCalls: function() {
|
||||
|
||||
@@ -56,8 +56,8 @@ class AudioCall:
|
||||
# send codec2 audio received from call receiver to call initiator over reticulum link
|
||||
RNS.Packet(self.link, data).send()
|
||||
|
||||
# gets the identity of the caller, or returns None if they did not identify
|
||||
def initiator_identity(self):
|
||||
# gets the identity of the other person, or returns None if they did not identify
|
||||
def get_remote_identity(self):
|
||||
return self.link.get_remote_identity()
|
||||
|
||||
# determine if this call is still active
|
||||
|
||||
77
web.py
77
web.py
@@ -254,24 +254,33 @@ class ReticulumWebChat:
|
||||
# get audio calls
|
||||
audio_calls = []
|
||||
for audio_call in self.audio_call_manager.audio_calls:
|
||||
|
||||
# get initiator identity hash
|
||||
initiator_identity_hash = None
|
||||
initiator_identity = audio_call.initiator_identity()
|
||||
if initiator_identity is not None:
|
||||
initiator_identity_hash = initiator_identity.hash.hex()
|
||||
|
||||
audio_calls.append({
|
||||
"hash": audio_call.link.hash.hex(),
|
||||
"initiator_identity_hash": initiator_identity_hash,
|
||||
"is_active": audio_call.is_active(),
|
||||
"is_outbound": audio_call.is_outbound,
|
||||
})
|
||||
audio_calls.append(self.convert_audio_call_to_dict(audio_call))
|
||||
|
||||
return web.json_response({
|
||||
"audio_calls": audio_calls,
|
||||
})
|
||||
|
||||
# get calls
|
||||
@routes.get("/api/v1/calls/{audio_call_link_hash}")
|
||||
async def index(request):
|
||||
|
||||
# get path params
|
||||
audio_call_link_hash = request.match_info.get("audio_call_link_hash", "")
|
||||
|
||||
# convert hash to bytes
|
||||
audio_call_link_hash = bytes.fromhex(audio_call_link_hash)
|
||||
|
||||
# find audio call
|
||||
audio_call = self.audio_call_manager.find_audio_call_by_link_hash(audio_call_link_hash)
|
||||
if audio_call is None:
|
||||
return web.json_response({
|
||||
"message": "audio call not found",
|
||||
}, status=404)
|
||||
|
||||
return web.json_response({
|
||||
"audio_call": self.convert_audio_call_to_dict(audio_call),
|
||||
})
|
||||
|
||||
# initiate a call to the provided destination
|
||||
@routes.get("/api/v1/calls/initiate/{destination_hash}")
|
||||
async def index(request):
|
||||
@@ -782,6 +791,48 @@ class ReticulumWebChat:
|
||||
"audio_call_address_hash": self.audio_call_manager.audio_call_receiver.destination.hexhash,
|
||||
}
|
||||
|
||||
# convert audio call to dict
|
||||
def convert_audio_call_to_dict(self, audio_call: AudioCall):
|
||||
|
||||
# get remote identity hash
|
||||
remote_identity_hash = None
|
||||
remote_identity = audio_call.get_remote_identity()
|
||||
if remote_identity is not None:
|
||||
remote_identity_hash = remote_identity.hash.hex()
|
||||
|
||||
# get remote destination hash
|
||||
# we need to know the remote identity to determine their destination hash
|
||||
remote_destination_hash = None
|
||||
if remote_identity is not None:
|
||||
remote_destination_hash = RNS.Destination.hash(remote_identity, "call", "audio")
|
||||
|
||||
# determine path to remote destination
|
||||
path = None
|
||||
if remote_destination_hash is not None:
|
||||
|
||||
# determine next hop and hop count
|
||||
hops = RNS.Transport.hops_to(remote_destination_hash)
|
||||
next_hop_bytes = self.reticulum.get_next_hop(remote_destination_hash)
|
||||
|
||||
# ensure next hop provided
|
||||
if next_hop_bytes is not None:
|
||||
next_hop = next_hop_bytes.hex()
|
||||
next_hop_interface = self.reticulum.get_next_hop_if_name(remote_destination_hash)
|
||||
path = {
|
||||
"hops": hops,
|
||||
"next_hop": next_hop,
|
||||
"next_hop_interface": next_hop_interface,
|
||||
}
|
||||
|
||||
return {
|
||||
"hash": audio_call.link.hash.hex(),
|
||||
"remote_destination_hash": remote_destination_hash.hex(),
|
||||
"remote_identity_hash": remote_identity_hash,
|
||||
"is_active": audio_call.is_active(),
|
||||
"is_outbound": audio_call.is_outbound,
|
||||
"path": path,
|
||||
}
|
||||
|
||||
# convert app data to string, or return none unable to do so
|
||||
def convert_app_data_to_string(self, app_data):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user