Files
IKAR/tool/verify_voice_transcription.dart
T

108 lines
3.5 KiB
Dart

import 'dart:convert';
import 'dart:io';
import '../lib/core/transport/ikar_network.dart';
import 'live_ikar_smoke.dart' as live;
Future<void> main() async {
final peers = <live.Device>[];
final client = IkarNetwork.client();
try {
final stamp = DateTime.now().microsecondsSinceEpoch.toString().substring(6);
for (var index = 0; index < 3; index++) {
peers.add(
await live.Device.create(
Uri.parse('https://ikar.kusoft.xyz'),
Platform.environment['IKAR_TEST_NODE'] ?? 'node',
'+999$stamp$index',
'Voice menu test $index',
),
);
}
final sender = peers[0], recipient = peers[1], outsider = peers[2];
final chatId = sender.id ^ recipient.id;
final info = (await sender.ok(87, {'count': 1}))['info'][0];
final uri = Uri.parse(
info['url'],
).replace(queryParameters: {'filename': 'ikar-speech-test.wav'});
final upload = await client.postUrl(uri);
upload.headers.contentType = ContentType('audio', 'wav');
upload.add(await File('artifacts/speech-test.wav').readAsBytes());
final response = await upload.close();
live.check(response.statusCode == 200, 'Voice upload rejected');
final token = jsonDecode(await utf8.decodeStream(response))['token'];
final sent = await sender.ok(64, {
'chatId': chatId,
'message': {
'attaches': [
{'_type': 'AUDIO', 'token': token, 'name': 'ikar-speech-test.wav'},
],
},
});
final message = sent['message'];
final messageId = message['id'];
final audioId = message['attaches'][0]['audioId'];
final completed = recipient.transport.events
.firstWhere(
(event) =>
event['opcode'] == 293 &&
event['payload']?['messageId'] == messageId,
)
.timeout(const Duration(seconds: 90));
final queued = await recipient.ok(202, {
'chatId': chatId,
'messageId': messageId,
'mediaId': audioId,
});
live.check(
queued['transcriptionStatus'] == 0 || queued['transcriptionStatus'] == 1,
'Voice menu request rejected',
);
final push = await completed;
final text = push['payload']['transcription'] as String;
live.check(text.contains('привет'), 'Speech recognition failed');
for (final peer in [sender, recipient]) {
final cached = await peer.ok(202, {
'chatId': chatId,
'messageId': messageId,
'mediaId': audioId,
});
live.check(
cached['transcriptionStatus'] == 1 && cached['transcription'] == text,
'Saved transcription missing',
);
}
final denied = await outsider.transport.request(202, {
'chatId': chatId,
'messageId': messageId,
'mediaId': audioId,
});
live.check(denied['cmd'] == 3, 'Transcription leaked to a nonmember');
final report = {
'passed': true,
'checks': [
'voice upload',
'recipient transcription request',
'completed recognition push',
'persisted text for both participants',
'nonmember denial',
],
'recognizedTestText': text,
'timestamp': DateTime.now().toUtc().toIso8601String(),
};
await File(
'artifacts/voice-transcription-live-verification.json',
).writeAsString(const JsonEncoder.withIndent(' ').convert(report));
stdout.writeln(jsonEncode(report));
} finally {
for (final peer in peers.reversed) {
try {
await peer.ok(199, {});
} finally {
await peer.close();
}
}
client.close(force: true);
}
}